POST 一般用来向服务端提交数据,HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。
<method> <request-URL> <version>
<headers>
<entity-body>
协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。
multipart/form-data:这是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 form 的 enctype 等于这个值。
请求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
这种方式一般用来上传文件(Content-Disposition后可接form-data表示表单数据,attachment表示附件)。RFC2183
消息主体<entity-body>里按照字段个数又分为多个结构类似的部分:
每部分都是以 --boundary 开始,紧接着内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如 text 的值就是 title
如果传输的是文件,还要包含文件名和文件类型(Content-Type)信息。如文件名为chrome.png的文件类型是image/png,具体内容(值)就是‘ PNG ... content of chrome.png ... ’ (二进制数据)
消息主体最后以 --boundary-- 标示结束。
参考资料:https://www.imququ.com/post/four-ways-to-post-data-in-http.html(挺好的资料)
下面分析web框架中分析post请求实体<entity-post>的代码:
# coding=utf-8
import cgi
def _to_unicode(s, encoding='utf-8'):
return s.decode('utf-8')
class MultipartFile(object):
def __init__(self, storage):
self.filename = _to_unicode(storage.filename)
self.file = storage.file
class Request(object):
def __init__(self, environ):
self._environ = environ
def _parse_input(self):
def _convert(item):
if is