閘道器協議學習:cgi、fastcgi、wsgi
簡單點說:
cgi
指令碼由http
伺服器啟動,通常用來處理使用者通過提交的資料。
通常,cgi
指令碼位於伺服器的專門的cgi-bin
目錄下。http
伺服器在指令碼的shell
環境中放置了請求相關的資訊,比如客戶端的hostname
,請求的url
,請求的字串以及其他東西。伺服器執行指令碼,並把輸出返回給客戶端。
指令碼的輸入也和客戶端相連,有時表單資料是通過這種方式讀取的。其他時候,表單資料是通過url
的query
字串傳遞的。這個模組用於處理不同的情況,提供乙個簡單的介面。同時提供了一些功能,幫助除錯指令碼。最近新增的功能是通過表單上傳檔案。
cgi
指令碼的輸出由兩部分組成,由乙個空行分割。第一部分包含一些頭部,告訴客戶接下來返回的是什麼資料。大概是這樣:
print("content-type: text/html") # 接下來返回的是html
print() # 空白行,頭部結束
第二部分,一般來說是html。客戶端軟體可以展示這些頁面,什麼的。
當你寫乙個新的指令碼時,新增下面這兩行:
import cgitb
cigtb.enable()
這將會啟用乙個異常處理器,如果發生了錯誤,它就會把錯誤返回給瀏覽器。如果你不想讓使用者看到,也可以指定輸出目錄。
import cgitb
cgitb.enable(display=0, logdir='/path/to/logdir')
補充:
可以通過post
請求提交資料有兩種方式multipart/form-data
。前者形如myvariableone=valueone&myvariabletwo=valuetwo
,使用%hh
的形式編碼非ascii碼,不接受重複鍵值。後者接受重複鍵值、二進位制檔案等。參考資料
fieldstorage
類獲取提交的表單資料,如果含有非asciii碼,使用encoding
引數,由於它會消耗標準資料,所以應該只被例項化1次。
fieldstorage
例項與python的字典相似。可以使用in
檢測內容,keys
,len
介面也都可以使用。fieldstorage
的每個值也是乙個fieldstorage
或者minifieldstorage
例項。
由於表單可能存在重複的專案名,你可以使用getlist()
方法。getlist(key_name)
方法會返回所有key
為key_name
的值。
如果上傳的表單中存在檔案,你可以呼叫值的read()
函式或者readline()
函式。
前面介紹了,如果使用fieldstorage
類從資料讀取cgi
。這一節,講述以西而更可讀和符合直覺的高階介面。但,前面講的技術還是有用的,比如高效處理檔案上傳。
該介面包含兩個方法。使用這戲方法你可以以更一般的方式處理資料,不用擔心是否有幾個值公用乙個名字。
form = cgi.fieldstorage()
item = form.getvalue("item")
if isinstance(item, list):
# handle the list
pass
else:
# handle the single value
pass
進行型別檢查是必須的,因為會有好事的使用者,輸入重複的鍵名。
你可以使用高階介面提供的getfirst()
和getlist()
方法。
大部分函式,如cgi.parse
,cgi.parse_qs
,cgi.parse_qsl
,已經被移植到urllib.parse
。cgi.escape
被移植到html.escape
。
原則:如果你啟動了乙個外部程式函式,永遠不要把使用者的輸入直接傳入shell
。即使要傳入也要確保只含有字母和數字、橫槓、下劃線和點。
閱讀你的http伺服器的文件,找到你的cgi
指令碼的安裝位置,一般是在伺服器目錄的cgi-bin
目錄下。
確保你的指令碼可被其他程式讀和執行;在unix
檔案模式下處於0o755
:使用chmod 0755 filename
。確保第一行有shebang
:
#! /usr/local/bin/python
同時,你的指令碼需要執行的檔案都有對應的許可權。因為你的伺服器被使用者nobody
執行,它只能讀/寫/執行那些被所有人讀/寫/執行的檔案。當前目錄和系統環境變數也可能可你目前所處的不一樣。
如果你需要從別的目錄引用模組,使用sys.path.insert(0, "/path/to/your/module")
這樣你的模組會被首先搜尋。
不行的是,當你從命令列嘗試cgi
指令碼是,它很有可能不會執行,而乙個能執行的cgi
指令碼往往在伺服器中不能執行。但你仍然應該從命令列中執行指令碼,檢查一下他是否有語法錯誤。如果你的指令碼沒有語法錯誤,但是它不工作,你只能讀下一節。
首先,檢查一下瑣碎的安裝錯誤,讀一下上面關於安裝的部分,能節約時間。如果你想知道你是否正確理解了安裝過程,把這個模組檔案cgi.py
安裝到你的cgi
指令碼目錄下,啟動這個指令碼,他就會將它的環境和內容以html的格式輸出。給他乙個合適的模式,傳送給他乙個請求。如果它被安裝在cgi-bin
目錄下,在你的瀏覽器內輸入如下url:
http://yourhostname/cgi-bin/c...\如果返回404錯誤,則說明伺服器沒有找到這個指令碼,或許你應該把它裝在別的目錄下。如果給了別的錯誤,說明你有安裝問題。你應該首先解決這些安裝問題,再做別的除錯。如果它給出了非常整潔的環境變數和表單內容輸出,說明
cgi.py
被正確的安裝了。如果,你的指令碼按上述過程安裝,你現在可以對他進行除錯了。
下一步是在你的指令碼中呼叫cgi
模組的test()
方法,把它的主要**替換成cgi.test
。
它應該輸出和僅安裝cgi.py
時一致。
當乙個普通的python指令碼丟擲了乙個未處理的異常時,python
直譯器會把traceback
列印出來,退出。當你的cgi
指令碼丟擲異常時,python
直譯器也會這麼做。這些traceback
一般會在你的http
伺服器的日誌檔案裡,或者被丟棄了。
幸運的是,如果你的指令碼執行了某些**,你可以通過啟用cgitb
模組,把traceback
的內容傳送到瀏覽器中。把下面兩行**加到你指令碼的頂部。
import cgitb
cgitb.enable()
如果你懷疑cgitb
模組有問題,你可以使用乙個更魯棒的方法,只呼叫內建模組:
import sys
sys.stderr = sys.stdout
print("content-type: text/plain")
print()
上述**依賴python
直譯器輸出traceback
,輸出的內容的格式被指定為純文字,去除了html
過程。如果你的指令碼正常工作,你的客戶端會顯示純html
。如果丟擲了異常,前兩行列印出之後,traceback
會被列印出來,如果沒有html
直譯器進行處理,所以traceback
會可讀。 官方文件之Cookie
蘋果文件翻譯內容 由於http協議的無狀態性,客戶端通常使用的持久化儲存資料都是來自於攜帶cookies的url網路請求 系統缺省會每次在傳送網路請求的時候在請求頭裡面設定cookie,我們通常沒有管理他,通過charles軟體抓包可以明顯的看到請求頭裡面多了個set cookie 引數 url l...
python官方 Python官方中文文件強勢來襲
python 官方支援的文件一直沒有中文。小夥伴們已經習慣了原汁原味的英文文件,但如果有官方中文文件,對於初學者來說,門檻會大大的降低。現在中文文件強勢來襲 以前也是有一些第三方維護的 python 中文文件,不過可能因為人力等限制,並做不到同步更新與維護。目前也有很多高質量的 python 中文資...
DRF官方文件之Response
responses rest framework提供了乙個response類來根據客戶端的請求方式返回不同型別的資料。response類繼承自django的 templateresponse。response物件會初始化python格式的資料。rest framework使用標準的http協議內容決...