2014-02-24 27 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/

免责声明:我是作者。当然,如果遇到错误,请创建一个问题。 :)

相关问题