Pengaturcaraan CGI Python3



Apakah itu CGI

CGI kini diselenggara oleh NCSA mentakrifkan CGI seperti berikut:

CGI (Antara Muka Gerbang Biasa), antara muka gerbang biasa, ia adalah. program , berjalan pada pelayan seperti: pelayan HTTP, menyediakan antara muka dengan halaman HTML klien.


Semakan imbas web

Untuk lebih memahami cara CGI berfungsi, kita boleh mulakan dengan proses mengklik pautan atau URL pada halaman web:

  • 1 Gunakan penyemak imbas anda untuk mengakses URL dan menyambung ke pelayan web HTTP.

  • 2. Selepas menerima maklumat permintaan, pelayan web akan menghuraikan URL dan menyemak sama ada fail yang diakses wujud pada pelayan Jika fail itu wujud, kembalikan kandungan fail tersebut. jika tidak mesej ralat akan dikembalikan.

  • 3. Penyemak imbas menerima maklumat daripada pelayan dan memaparkan fail atau mesej ralat yang diterima.

Atur cara CGI boleh menjadi skrip Python, skrip PERL, skrip SHELL, program C atau C++, dsb.


Rajah seni bina CGI

Cgi01.png


Sokongan dan konfigurasi pelayan web

Sebelum anda melakukan pengaturcaraan CGI, pastikan anda Pelayan web menyokong CGI dan mempunyai pengendali CGI dikonfigurasikan.

Apache menyokong konfigurasi CGI:

Sediakan direktori CGI:

ScriptAlias /cgi-bin/ /var/www/cgi-bin/

Semua program CGI pelaksanaan pelayan HTTP disimpan dalam direktori pra-konfigurasi. Direktori ini dipanggil direktori CGI, dan mengikut konvensyen, ia dinamakan /var/www/cgi-bin.

Sambungan fail CGI ialah .cgi, dan python juga boleh menggunakan sambungan .py.

Secara lalai, direktori cgi-bin tempat pelayan Linux dikonfigurasikan untuk dijalankan ialah /var/www.

Jika anda ingin menentukan direktori lain untuk menjalankan skrip CGI, anda boleh mengubah suai fail konfigurasi httpd.conf seperti berikut:

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options +ExecCGI
   Order allow,deny
   Allow from all
</Directory>

Tambah akhiran .py dalam AddHandler supaya kami boleh mengaksesnya Fail skrip python yang berakhir dengan py:

AddHandler cgi-script .cgi .pl .py

Atur cara CGI pertama

Kami menggunakan Python untuk mencipta program CGI yang pertama, nama fail ialah hello.py, dan fail itu ialah terletak dalam /var/ Dalam direktori www/cgi-bin, kandungannya adalah seperti berikut:

#!/usr/bin/python3

print ("Content-type:text/html")
print ()                             # 空行,告诉服务器结束头部
print ('<html>')
print ('<head>')
print ('<meta charset="utf-8">')
print ('<title>Hello Word - 我的第一个 CGI 程序!</title>')
print ('</head>')
print ('<body>')
print ('<h2>Hello Word! 我是来自php中文网的第一CGI程序</h2>')
print ('</body>')
print ('</html>')

Selepas menyimpan fail, ubah suai hello.py dan ubah suai kebenaran fail kepada 755:

chmod 755 hello.py

Atur cara di atas akan memaparkan hasil berikut apabila diakses oleh penyemak imbas:

1026.jpg

Skrip hello.py ini ialah skrip Python yang ringkas Kandungan keluaran baris pertama skrip "Content-type: text/html" dihantar ke penyemak imbas dan memberitahu penyemak imbas Jenis kandungan yang dipaparkan oleh penyemak imbas ialah "teks/html".

Gunakan cetakan untuk mengeluarkan baris kosong untuk memberitahu pelayan menamatkan maklumat pengepala.


Pengepala HTTP

"Content-type: text/html" dalam kandungan fail hello.py ialah sebahagian daripada pengepala HTTP, yang akan dihantar kepada penyemak imbas untuk memberitahu pelayar Jenis kandungan fail pelayan.

Format pengepala HTTP adalah seperti berikut:

HTTP 字段名: 字段内容

Contohnya:

Content-type: text/html

Jadual berikut memperkenalkan maklumat yang biasa digunakan dalam pengepala HTTP dalam program CGI:

描述
Content-type:请求的与实体对应的MIME信息。例如: Content-type:text/html
Expires: Date响应过期的日期和时间
Location: URL用来重定向接收方到非请求URL的位置来完成请求或标识新的资源
Last-modified: Date请求资源的最后修改时间
Content-length: N请求的内容长度
Set-Cookie: String设置Http Cookie

Pembolehubah persekitaran CGI

Semua program CGI menerima pembolehubah persekitaran berikut, yang memainkan peranan penting dalam program CGI:

变量名描述
CONTENT_TYPE这个环境变量的值指示所传递来的信息的MIME类型。目前,环境变量CONTENT_TYPE一般都是:application/x-www-form-urlencoded,他表示数据来自于HTML表单。
CONTENT_LENGTH如果服务器与CGI程序信息的传递方式是POST,这个环境变量即使从标准输入STDIN中可以读到的有效数据的字节数。这个环境变量在读取所输入的数据时必须使用。
HTTP_COOKIE客户机内的 COOKIE 内容。
HTTP_USER_AGENT提供包含了版本数或其他专有数据的客户浏览器信息。
PATH_INFO这个环境变量的值表示紧接在CGI程序名之后的其他路径信息。它常常作为CGI程序的参数出现。
QUERY_STRING如果服务器与CGI程序信息的传递方式是GET,这个环境变量的值即使所传递的信息。这个信息经跟在CGI程序名的后面,两者中间用一个问号'?'分隔。
REMOTE_ADDR这个环境变量的值是发送请求的客户机的IP地址,例如上面的192.168.1.67。这个值总是存在的。而且它是Web客户机需要提供给Web服务器的唯一标识,可以在CGI程序中用它来区分不同的Web客户机。
REMOTE_HOST这个环境变量的值包含发送CGI请求的客户机的主机名。如果不支持你想查询,则无需定义此环境变量。
REQUEST_METHOD提供脚本被调用的方法。对于使用 HTTP/1.0 协议的脚本,仅 GET 和 POST 有意义。
SCRIPT_FILENAMECGI脚本的完整路径
SCRIPT_NAMECGI脚本的的名称
SERVER_NAME这是你的 WEB 服务器的主机名、别名或IP地址。
SERVER_SOFTWARE这个环境变量的值包含了调用CGI程序的HTTP服务器的名称和版本号。例如,上面的值为Apache/2.2.14(Unix)

Berikut ialah skrip CGI ringkas yang mengeluarkan pembolehubah persekitaran CGI:

#!/usr/bin/python3

import os

print ("Content-type: text/html")
print ()
print ("<meta charset=\"utf-8\">")
print ("<b>环境变量</b><br>")
print ("<ul>")
for key in os.environ.keys():
    print ("<li><span style='color:green'>%30s </span> : %s </li>" % (key,os.environ[key]))
print ("</ul>")

Simpan titik di atas sebagai test.py dan ubah suai kebenaran fail kepada 755. Keputusan pelaksanaan adalah seperti berikut:

1027.jpg


Kaedah GET dan POST

Pelanggan penyemak imbas menghantar maklumat ke pelayan melalui dua kaedah, dua kaedah tersebut ialah kaedah GET dan kaedah POST.

Gunakan kaedah GET untuk menghantar data

Kaedah GET menghantar maklumat pengguna yang dikodkan ke pelayan Maklumat data disertakan dalam URL halaman yang diminta, dipisahkan dengan "?", seperti yang ditunjukkan di bawah:

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
Beberapa nota lain tentang permintaan GET:
  • Permintaan GET boleh dicache

  • Permintaan GET kekal dalam sejarah penyemak imbas

  • Permintaan GET boleh ditanda buku

  • Permintaan GET tidak boleh digunakan semasa mengendalikan data sensitif

  • GET permintaan mempunyai sekatan panjang

  • Permintaan GET hanya boleh digunakan untuk mendapatkan data

Contoh url mudah: Kaedah GET

Yang berikut ialah URL ringkas yang menggunakan kaedah GET untuk menghantar dua parameter kepada program hello_get.py:

/cgi-bin/test.py?name=php中文网&url=http://www.php.cn

Berikut ialah kod untuk fail hello_get.py:

#!/usr/bin/python3

# CGI处理模块
import cgi, cgitb 

# 创建 FieldStorage 的实例化
form = cgi.FieldStorage() 

# 获取数据
site_name = form.getvalue('name')
site_url  = form.getvalue('url')

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>php中文网 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2>%s官网:%s</h2>" % (site_name, site_url))
print ("</body>")
print ("</html>")

Ubah suai hello_get selepas menyimpan py, ubah suai kebenaran fail kepada 755:

chmod 755 hello_get.py

Hasil keluaran permintaan penyemak imbas:

1028.jpg

Contoh bentuk mudah: kaedah GET

di bawah Ini adalah borang HTML yang menggunakan kaedah GET untuk menghantar dua data ke pelayan Skrip pelayan yang diserahkan juga adalah fail hello_get.py Kod hello_get.html adalah seperti berikut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/hello_get.py" method="get">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>

Secara lalai. , direktori cgi-bin hanya boleh disimpan Untuk fail skrip, kami menyimpan hello_get.html dalam direktori ujian dan mengubah suai kebenaran fail kepada 755:

chmod 755 hello_get.html

Demo gif adalah seperti berikut:

hello_get.gif

Gunakan Kaedah POST untuk memindahkan data

Menggunakan kaedah POST untuk memindahkan data ke pelayan adalah lebih selamat dan boleh dipercayai Beberapa maklumat sensitif seperti kata laluan pengguna perlu menggunakan POST untuk memindahkan data.

Berikut ialah hello_get.py, yang juga boleh memproses data borang POST yang diserahkan oleh penyemak imbas:

#!/usr/bin/python3

# CGI处理模块
import cgi, cgitb 

# 创建 FieldStorage 的实例化
form = cgi.FieldStorage() 

# 获取数据
site_name = form.getvalue('name')
site_url  = form.getvalue('url')

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>php中文网 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2>%s官网:%s</h2>" % (site_name, site_url))
print ("</body>")
print ("</html>")

Berikut ialah borang melalui kaedah POST (method="post" ) Hantar data ke skrip pelayan hello_get.py:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/hello_get.py" method="post">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>
</form>

Demonstrasi GIF adalah seperti berikut:

hello_post.gif

Lulus data kotak semak melalui program CGI

Kotak semak digunakan untuk menyerahkan satu atau lebih data pilihan Kod HTML adalah seperti berikut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/checkbox.py" method="POST" target="_blank">
<input type="checkbox" name="php" value="on" /> php中文网
<input type="checkbox" name="google" value="on" /> Google
<input type="submit" value="选择站点" />
</form>
</body>
</html>

Berikut ialah kod fail checkbox.py:

#!/usr/bin/python3

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('google'):
   google_flag = "是"
else:
   google_flag = "否"

if form.getvalue('php'):
   php_flag = "是"
else:
   php_flag = "否"

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>php中文网 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2> php中文网是否选择了 : %s</h2>" % php_flag)
print ("<h2> Google 是否选择了 : %s</h2>" % google_flag)
print ("</body>")
print ("</html>")

Ubah suai kotak semak. .py kebenaran:

chmod 755 checkbox.py

Akses pelayar demo Gif:

checkbox.gif

Pindahkan data Radio melalui program CGI

Radio hanya menghantar satu data ke pelayan, kod HTML adalah seperti berikut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/radiobutton.py" method="post" target="_blank">
<input type="radio" name="site" value="php" /> php中文网
<input type="radio" name="site" value="google" /> Google
<input type="submit" value="提交" />
</form>
</body>
</html>

radiobutton.py Kod skrip adalah seperti berikut:

#!/usr/bin/python3

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('site'):
   site = form.getvalue('site')
else:
   site = "提交数据为空"

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>php中文网 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2> 选中的网站是 %s</h2>" % site)
print ("</body>")
print ("</html>")

Ubah suai kebenaran radiobutton .py:

chmod 755 radiobutton.py

Imej Demo Gif Akses penyemak imbas:

radiobutton.gif

Pindahkan data Textarea melalui program CGI

Textarea memindahkan berbilang mesej ke data Baris pelayan, kod HTML adalah seperti berikut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/textarea.py" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4">
在这里输入内容...
</textarea>
<input type="submit" value="提交" />
</form>
</body>
</html>

textarea.py Kod skrip adalah seperti berikut:

#!/usr/bin/python3

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "没有内容"

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>php中文网 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2> 输入的内容是:%s</h2>" % text_content)
print ("</body>")
print ("</html>")

Ubah suai textarea.py Keizinan:

chmod 755 textarea.py

Imej demo Gif akses penyemak imbas:

textarea.gif

Haluskan data lungsur turun melalui program CGI.

Kod kotak lungsur HTML adalah seperti berikut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/dropdown.py" method="post" target="_blank">
<select name="dropdown">
<option value="php" selected>php中文网</option>
<option value="google">Google</option>
</select>
<input type="submit" value="提交"/>
</form>
</body>
</html>

kod skrip dropdown.py adalah seperti berikut:

#!/usr/bin/python3

# 引入 CGI 处理模块 
import cgi, cgitb 

# 创建 FieldStorage的实例 
form = cgi.FieldStorage() 

# 接收字段数据
if form.getvalue('dropdown'):
   dropdown_value = form.getvalue('dropdown')
else:
   dropdown_value = "没有内容"

print ("Content-type:text/html")
print ()
print ("<html>")
print ("<head>")
print ("<meta charset=\"utf-8\">")
print ("<title>php中文网 CGI 测试实例</title>")
print ("</head>")
print ("<body>")
print ("<h2> 选中的选项是:%s</h2>" % dropdown_value)
print ("</body>")
print ("</html>")

Ubah suai kebenaran dropdown.py:

chmod 755 dropdown.py

Pelayar Lawati imej demo Gif:

dropdown.gif


Menggunakan Kuki dalam CGI

Kelemahan besar protokol http ialah ia tidak menilai identiti pengguna. Ia membawa ketidakselesaan besar kepada pengaturcara. Kemunculan fungsi kuki menggantikan kekurangan ini.

Kuki adalah untuk menulis data rekod pada pemacu keras pelanggan melalui penyemak imbas pelanggan apabila pelanggan mengakses skrip. , maklumat data akan diambil pada kali seterusnya pelanggan mengakses skrip, untuk mencapai fungsi diskriminasi identiti Kuki sering digunakan dalam pengesahan identiti.

 

Sintaks kuki

Kuki http dihantar melalui pengepala http, yang lebih awal daripada pemindahan fail Sintaks set-cookie dalam pengepala adalah seperti berikut:

Set-cookie:name=name;expires=date;path=path;domain=domain;secure
<🎜. >
  • name=name: Anda perlu menetapkan nilai kuki (nama tidak boleh menggunakan ";" dan ","), bagaimana banyak Gunakan ";" untuk memisahkan nilai nama, contohnya: name1=name1;name2=name2;name3=name3.

  • tamat=tarikh: Tempoh sah kuki, format: luput="Wdy,DD-Mon-YYYY HH:MM:SS"


  • path=path: Tetapkan laluan yang disokong oleh kuki Jika laluan ialah laluan, kuki akan berada dalam ini direktori. Sah untuk semua fail dan subdirektori, contohnya: path="/cgi-bin/". cgi".

  • domain=domain: Nama domain yang sah untuk kuki, contohnya: domain="www.php.cn"

  • selamat: Jika bendera ini diberikan, ini bermakna kuki hanya boleh dihantar melalui pelayan https protokol SSL.

  • Penerimaan kuki dicapai dengan menetapkan pembolehubah persekitaran Program CGI HTTP_COOKIE boleh mendapatkan maklumat kuki dengan mendapatkan semula pembolehubah ini.


Tetapan Kuki

Tetapan kuki adalah sangat mudah dan kuki akan dihantar secara berasingan dalam pengepala http. Contoh berikut menetapkan nama dan tamat tempoh dalam kuki:

#!/usr/bin/python3
# 
print ('Content-Type: text/html')
print ('Set-Cookie: name="php中文网";expires=Wed, 28 Aug 2016 18:30:00 GMT')
print ()
print ("""
<html>
  <head>
    <meta charset="utf-8">
    <title>php中文网(php.cn)</title>
  </head>
    <body>
        <h1>Cookie set OK!</h1>
    </body>
</html>
""")

Simpan kod di atas ke cookie_set.py, dan ubah suai keizinan cookie_set.py:

chmod 755 cookie_set.py

Contoh di atas menggunakan Set- Maklumat pengepala kuki Untuk menetapkan maklumat Kuki, atribut lain Kuki ditetapkan dalam pilihan pilihan, seperti masa tamat tempoh Tamat, nama domain dan laluan. Maklumat ini ditetapkan sebelum "Content-type:text/html".


Dapatkan Maklumat Kuki

Halaman perolehan maklumat Kuki adalah sangat mudah disimpan dalam pembolehubah persekitaran CGI HTTP_COOKIE Format storan adalah seperti berikut:

rreee

Berikut ialah program CGI Mudah untuk mendapatkan maklumat kuki:

key1=value1;key2=value2;key3=value3....

Simpan kod di atas ke cookie_get.py dan ubah suai kebenaran cookie_get.py:

#!/usr/bin/python3

# 导入模块
import os
import Cookie

print ("Content-type: text/html")
print ()

print ("""
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<h1>读取cookie信息</h1>
""")

if 'HTTP_COOKIE' in os.environ:
    cookie_string=os.environ.get('HTTP_COOKIE')
    c=Cookie.SimpleCookie()
    c.load(cookie_string)

    try:
        data=c['name'].value
        print ("cookie data: "+data+"<br>")
    except KeyError:
        print ("cookie 没有设置或者已过去<br>")
print ("""
</body>
</html>
""")

Warna tetapan kuki di atas Gif adalah seperti berikut:

cookie.gif

Contoh muat naik fail

Borang tetapan HTML untuk memuat naik fail perlu menetapkan atribut enctype kepada multipart/form-data , kodnya adalah seperti berikut:

chmod 755 cookie_get.py

save_file.py skrip kod fail adalah seperti berikut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
 <form enctype="multipart/form-data" 
                     action="/cgi-bin/save_file.py" method="post">
   <p>选中文件: <input type="file" name="filename" /></p>
   <p><input type="submit" value="上传" /></p>
   </form>
</body>
</html>

Simpan kod di atas untuk save_file.py, dan ubah suai save_file.py kebenaran:

#!/usr/bin/python3

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# 获取文件名
fileitem = form['filename']

# 检测文件是否上传
if fileitem.filename:
   # 设置文件路径 
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = '文件 "' + fn + '" 上传成功'
   
else:
   message = '文件没有上传'
   
print ("""\
Content-Type: text/html\n
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,))

Warna tetapan kuki di atas Gif adalah seperti berikut:

savefile.gif

Jika sistem yang anda gunakan ialah Unix/Linux, anda mesti gantikan pemisah fail. Di bawah tetingkap, anda hanya perlu menggunakan pernyataan open( ):

chmod 755 save_file.py

Kotak dialog muat turun fail

Kami mula-mula mencipta fail foo.txt dalam direktori semasa untuk memuat turun program.

Muat turun fail dicapai dengan menetapkan maklumat pengepala HTTP Kod fungsi adalah seperti berikut:

fn = os.path.basename(fileitem.filename.replace("\", "/" ))