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中提交内容的方式。

tornado解析http body的过程分析的更多相关文章

  1. tornado解析post数据的问题

    解析tornado查询参数: self.request.query_arguments self.get_query_argument[s](参数名称) 解析tornado的post参数: self. ...

  2. tornado解析 第一篇

    一.tornado介绍 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 we ...

  3. spring beans源码解读之--XmlBeanFactory

    导读: XmlBeanFactory继承自DefaultListableBeanFactory,扩展了从xml文档中读取bean definition的能力.从本质上讲,XmlBeanFactory等 ...

  4. 《AngularJs实战》学习笔记(慕课网)

    1. Controller使用过程中的注意点 不要试图去复用Controller, 一个控制器一般只负责一小块视图 不要在Controller中操作DOM, 这不是控制器的职责. 封装在指令里. 不要 ...

  5. Android系统Recovery工作原理之使用update.zip升级过程分析(八)---解析并执行升级脚本updater-script【转】

    本文转载自:http://blog.csdn.net/mu0206mu/article/details/7465551  Android系统Recovery工作原理之使用update.zip升级过程分 ...

  6. Python+Tornado+Tampermonkey 获取某讯等主流视频网站的会员视频解析播放

    近期,<哪吒之魔童降世>在各大视频软件可以看了,然而却是一贯的套路,非会员谢绝观看!!!只能从国内那些五花八门的视频网站上找着看了,或者通过之前本人说的 Chrome 的油猴插件,传送门  ...

  7. tornado反向解析

    tornado反向解析 在路由中添加name属性,并且不能使用元组路由,应当由tornado.web.url定义路由. app = tornado.web.Application([ (r'/', I ...

  8. Netty 源码解析(九): connect 过程和 bind 过程分析

    原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 今天是猿灯塔“365篇原创计划”第九篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源 ...

  9. Linux移植之tag参数列表解析过程分析

    在Linux移植之内核启动过程start_kernel函数简析中已经指出了start_kernel函数的调用层次,这篇主要是对具体的tag参数列表进行解析. 1.内存参数ATAG_MEM参数解析 2. ...

随机推荐

  1. js实现移动端无限加载分页

    原理:当滚动条到达底部时,执行下一页内容. 判断条件需要理解三个概念:    1.scrollHeight 真实内容的高度    2.clientHeight 视窗的高度,即在浏览器中所能看到的内容的 ...

  2. 对象属性封装到map中

    import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.lang.reflect.Modi ...

  3. Java--CJDP

    was定义,包定义, 1. Java的接口概念 进行封装,方便的使用 2. 包定义,Java 中多种包,进行迁移使用,包的导入,例如对数据库的操作Hibernate 3. 配置文件xml和json,对 ...

  4. 《DDNS服务器的搭建和案例解决方法》

    DDNS原理:DNS + DHCP =DDNS DHCP负责ip解析,和分配给客户机ip,ip为随机数. DNS负责域名解析,A记录里记录了每个ip对应的域名. 客户端ip肯定是变化的,不可能一直使用 ...

  5. Linux C 程序 进程控制(17)

    进程控制 1.进程概述现代操作系统的特点在于程序的并行执行.Linux是一个多用户多任务的操作系统.ps .pstree 查看进程进程除了进程id外还有一些其他标识信息,可以通过相应的函数获得.// ...

  6. C#主要支持 5 种动态创建对象的方式

    C#主要支持 5 种动态创建对象的方式: 1. Type.InvokeMember 2. ContructorInfo.Invoke 3. Activator.CreateInstance(Type) ...

  7. Nginx之负载均衡

    转自:http://www.360doc.com/content/13/1114/12/7694408_329125489.shtml 注,大家可以看到,由于我们网站是发展初期,nginx只代理了后端 ...

  8. 重拾C,一天一点点_5

    switch(表达式){    case 整型常量表达式:语句序列    case 整型常量表达式:语句序列    default:语句序列} while(表达式)    语句 for(表达式1; 表 ...

  9. 使用cookie解决微信不能存储localStorage的问题

    最近在开发基于微信的Web页面时,发现有些机型不能存储信息到localStorage中,或者是页面一旦关闭,存储的信息也失效了. 于是想到用cookie来替代localStorage,存储一些简单的数 ...

  10. 编写php拓展实例--slime项目(用户登录会话类)

      最近公司换了yaf框架,突然对用c实现php拓展感兴趣了,如果一个功能已经很稳定很成熟而且用的地方很多,那么我们就可以尝试用拓展实现(不一定每种情况都可以写成拓展),写成拓展后就不用每次用都包含一 ...