tornado解析http body的過程分析


tornado解析http body的過程分析

在最近寫的一個RESTful API Server過程中,發現tornaod對解析POST BODY的內容有限制。

而在以前用web.py則沒有這個限制,使用httplib2作為客戶端。

客戶端代碼:

復制代碼
def request(self, url, method, **kwargs):
        request_kwargs = copy.copy(kwargs)
        request_kwargs.setdefault('headers', kwargs.get('headers', {}))
        request_kwargs['headers']['Accept'] = 'application/json'
        request_kwargs['headers']['Content-type'] = 'application/x-www-form-urlencoded'
        try:
            request_kwargs['body']['token'] = self.token
            request_kwargs['body'] = urllib.urlencode(kwargs['body'])
        except KeyError:
            pass
        resp, body = super(HTTPClient, self).request(self.api_url + url, method, **request_kwargs)
        
        return resp, body
復制代碼

上面加粗的部分中,設置header的Content-type參數,為 application/x-www-form-urlencoded,否則tornado不會解析request body中的內容。

 

tornado解析uri中參數的過程就不解釋了,關鍵的地方是解析body中的內容。

body中可以有兩種類型的內容,一為form提交的,二為被urlencod過的內容(也放在body)里面。

因為httplib2在使用POST/PUT/PATCH提交body內容時,不會自動設置Content-type參數,導致了tornado找不到對應的類型。

在使用self.get_argument函數時,根本得不到字段的內容。

關鍵代碼:

首先是在HTTPConnection類中的_on_request_body回調函數:

復制代碼
1 def _on_request_body(self, data):
2         self._request.body = data
3         if self._request.method in ("POST", "PATCH", "PUT"):
4             httputil.parse_body_arguments(
5                 self._request.headers.get("Content-Type", ""), data,
6                 self._request.arguments, self._request.files)
7         self.request_callback(self._request)
復制代碼

httputil.parse_body_arguments函數完成對客戶端使用POST/PATCH/PUT方法時,BODY內容的解析:

復制代碼
 1 def parse_body_arguments(content_type, body, arguments, files):
 2     """Parses a form request body.
 3 
 4     Supports "application/x-www-form-urlencoded" and "multipart/form-data".
 5     The content_type parameter should be a string and body should be
 6     a byte string.  The arguments and files parameters are dictionaries
 7     that will be updated with the parsed contents.
 8     """
 9     if content_type.startswith("application/x-www-form-urlencoded"):
10         uri_arguments = parse_qs_bytes(native_str(body))
11         for name, values in uri_arguments.iteritems():
12             values = [v for v in values if v]
13             if values:
14                 arguments.setdefault(name, []).extend(values)
15     elif content_type.startswith("multipart/form-data"):
16         fields = content_type.split(";")
17         for field in fields:
18             k, sep, v = field.strip().partition("=")
19             if k == "boundary" and v:
20                 parse_multipart_form_data(utf8(v), body, arguments, files)
21                 break
22         else:
23             logging.warning("Invalid multipart/form-data")
復制代碼

函數的注釋里面已經寫的很清楚了:

Supports "application/x-www-form-urlencoded" and "multipart/form-data".

只支持 application/x-www-form-urlencoded 和 multipart/form-data這兩種在body中提交內容的方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM