2014-02-24 59 views
0

所以我一直在Python中編寫一個簡單的Web服務器,現在我試圖處理多部分/表單數據POST請求。我已經可以處理application/x-www-form-urlencoded POST請求,但相同的代碼不適用於multipart。如果看起來我誤解了任何東西,請給我打電話,即使它很小。此外,如果你們有任何建議使我的代碼更好,請讓我知道以及:)謝謝!Python服務器cgi.FieldStorage解析多部分/表單數據

當請求到來時,我首先解析它,然後將它分解成一個包含請求正文的頭文件和字符串的字典。我用那些然後構造一個的FieldStorage形式,然後我就可以像對待字典拉出來的數據:

requestInfo = '' 
while requestInfo[-4:] != '\r\n\r\n': 
    requestInfo += conn.recv(1) 

requestSplit = requestInfo.split('\r\n')[0].split(' ') 
requestType = requestSplit[0] 

url = urlparse.urlparse(requestSplit[1]) 
path = url[2] # Grab Path 

if requestType == "POST": 
    headers, body = parse_post(conn, requestInfo) 

    print "!!!Request!!! " + requestInfo 
    print "!!!Body!!! " + body 
    form = cgi.FieldStorage(headers = headers, fp = StringIO(body), environ = {'REQUEST_METHOD':'POST'}, keep_blank_values=1) 

這裏是我的parse_post方法:

def parse_post(conn, headers_string): 
    headers = {} 
    headers_list = headers_string.split('\r\n') 

    for i in range(1,len(headers_list)-2): 
     header = headers_list[i].split(': ', 1) 
     headers[header[0]] = header[1] 

    content_length = int(headers['Content-Length']) 

    content = conn.recv(content_length) 

    # Parse Content differently if it's a multipart request?? 

    return headers, content 

因此,對於一個X WWW-窗體-urlencoded POST請求,我可以治療的FieldStorage形式像字典一樣,如果我打電話,例如:

firstname = args['firstname'].value 
print firstname 

它將工作。但是,如果我發送多部分POST請求,它最終不會打印任何內容。

這是X WWW的窗體-urlencoded請求的主體中: 姓名= TEST &姓氏= rwar

這是多部分請求的主體: --070f6a3146974d399d97c85dcf93ed44 內容處置:形式-數據; NAME = 「姓氏」; filename =「lastname」

rwar --070f6a3146974d399d97c85dcf93ed44 Content-Disposition:form-data; NAME = 「姓名」;文件名=「名字」

TEST --070f6a3146974d399d97c85dcf93ed44--

所以這裏的問題,我應該手動解析機構在parse_post的數據,如果它是一個多要求?

還是有一種方法,我需要/可以用來解析多部分機構?

或者我是否完全犯這個錯誤?再次

謝謝,我知道這是一個漫長的閱讀,但我想確保我的問題是全面

+0

你是否正在做一個Web服務器實現的任何實際原因?已經有很多(很多)很好的Web服務器實現。嘗試簡單需求的標準庫中的SimpleHTTPServer'或嚴重需求的nginx + uwsgi。 – SingleNegationElimination

+0

不,我只是在學習這些庫的較低級別的內容,儘管我從來沒有聽說過SimpleHTTPServer,但我必須牢記這一點,謝謝! –

回答

2

所以,我解決我的問題,但在一個完全哈克的方式。

端了手動解析請求的主體,這是我寫的代碼:

if("multipart/form-data" in headers["Content-Type"]): 
    data_list = [] 
    content_list = content.split("\r\n\r\n") 
    for i in range(len(content_list) - 1): 
     data_list.append("") 

    data_list[0] += content_list[0].split("name=")[1].split(";")[0].replace('"','') + "=" 

    for i,c in enumerate(content_list[1:-1]): 
     key = c.split("name=")[1].split(";")[0].replace('"','') 
     data_list[i+1] += key + "=" 
     value = c.split("\r\n") 
     data_list[i] += value[0] 

    data_list[-1] += content_list[-1].split("\r\n")[0] 

    content = "&".join(data_list) 

如果有人仍然可以解決我的問題,而不必手動解析身體,請讓我知道!

0

有一個流式表單數據項目,它提供了一個Python解析器來解析編碼爲multipart/form-data的數據。它旨在允許以塊的形式解析數據,但由於沒有強制執行塊大小,所以您可以立即傳遞整個輸入,並且它應該可以完成這項工作。它應該可以通過pip install streaming_form_data進行安裝。

這裏的源代碼 - https://github.com/siddhantgoel/streaming-form-data

文檔 - https://streaming-form-data.readthedocs.io/en/latest/

免責聲明:我是作者。當然,如果遇到錯誤,請創建一個問題。 :)

相關問題