http伺服器究竟做了什麼(三)
阿新 • • 發佈:2019-01-10
本節內容將通過一些示例來說明CGI程式.前面講過CGI程式可以用任何語言編寫,考慮到便捷性,這裡用python來展示CGI程式.
首先搭建伺服器.我這裡用了最輕量級的http伺服器tinyhttp,總共程式碼只有500行左右,後面的伺服器程式碼分析也是基於這個.在他的htdocs裡新增一個test.cgi,寫CGI程式碼.注意,test.cgi指令碼要有可執行的的許可權,否則訪問test.cgi時,將直接讀取裡面的文字,而不是執行該檔案. test.cgi程式碼如下:
#!/usr/bin/python #注意要新增這行,表示該檔案會被python解析器解析 # -*- coding: UTF-8 -*- print "Content-type:text/html" print # 空行,告訴伺服器結束頭部 print '<html>' print '<head>' print '<meta charset="utf-8">' print '<title>Hello World - 我的第一個 CGI 程式!</title>' print '</head>' print '<body>' print '<h2>Hello World! 我是第一個CGI程式</h2>' print '</body>' print '</html>'
開啟我們的伺服器,訪問/test.cgi,瀏覽器會得到:
Hello World! 我是第一個CGI程式
我做實驗時,第一次沒有顯示,報錯資訊/usr/bin/python^M: bad interpreter: No such file or directory. 是因為cgi文字格式為dos,用vim set ff=unix就可以改過來了.
我們再來梳理一下瀏覽器得到這個結果的過程:
瀏覽器發起請求,伺服器收到請求,轉給CGI程式處理.CGI列印一段簡單的http文字,重定向給伺服器,伺服器返回給瀏覽器,然後我們就看到了結果.
列印環境變數:
#!/usr/bin/python # -*- coding: UTF-8 -*- import os print "Content-type:text/html" print # 空行,告訴伺服器結束頭部 print '<html>' print '<meta charset=\"utf-8\">' print '<b>環境變數</b><br>' print '<ul>' list_env = ['REQUEST_METHOD', 'QUERY_STRING', 'CONTENT_LENGTH', 'CONTENT_TYPE','CONTENT_FILE','PATH_INFO','PATH_TRANSLATED','SCRIPT_NAME'] for key in os.environ.keys(): if key in list_env: print "<li><span style='color:green'>%30s </span> : %s </li>" % (key, os.environ[key])
請求 /test.cgi?name=shonm&age=25 得到的結果為:
我們再來看post的結果,html的頁面程式碼為:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>測試post</title> </head> <body> <form action="/test.cgi" method="post"> 姓名: <input type="text" name="name"> <br /> 年齡: <input type="text" name="age" /> <input type="submit" value="提交" /> </form> </body> </html>
/test.cgi:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os,cgi
print "Content-type:text/html"
print # 空行,告訴伺服器結束頭部
print '<html>'
print '<meta charset=\"utf-8\">'
print '<b>環境變數</b><br>'
print '<ul>'
list_env = ['REQUEST_METHOD', 'QUERY_STRING', 'CONTENT_LENGTH',
'CONTENT_TYPE','CONTENT_FILE','PATH_INFO','PATH_TRANSLATED','SCRIPT_NAME']
for key in os.environ.keys():
if key in list_env:
print "<li><span style='color:green'>%30s </span> : %s </li>" % (key, os.environ[key])
if os.environ['REQUEST_METHOD'] == 'POST':
# 建立 FieldStorage 的例項化
form = cgi.FieldStorage()
# 獲取資料
name = form.getvalue('name')
age = form.getvalue('age')
print '<br> name is %s, age is %s ' %(name, age)
點選提交,得到:
POST請求,在環境變數中沒有關於請求內容的欄位,只有內容的長度,根據這個長度,然後伺服器再次讀取socket獲取內容.上面的內容為:'name=shonm&age=25',和用GET請求(可以改form method = 'get')時QUERY_STRING欄位的內容一致.