flask http post form parse

原创
2013/12/12 12:17
阅读数 431

和同事联调一个web service,他那边使用HTTP POST来检验验证码是否有效,结果他说每次都返回400,我看了日志,发现我没有取到POST的内容。

先看一段代码 app.py

# -*- coding: utf8 -*-

from flask import Flask, request, jsonify


app = Flask(__name__)


@app.route('/index', methods=['POST', ])
def index():
    uid = request.form.get('uid', None)
    code = request.form.get('code', None)

    return jsonify(uid=uid, code=code)

if __name__ == '__main__':
    app.run(debug=True, use_reloader=True)

运行上述代码,使用curl来测试一下,看看是否有数据返回:

curl -X POST http://127.0.0.1:5000/index --data "uid=12x31&code=x164d"

结果是有数据,返回正常:

{
  "code": "x164d", 
  "uid": "12x31"
}

于是乎,我告诉他跑这个列子试试,他说可以通过测试,但是,自己写的程序就是没有正确 返回,尝试抓了一下包,两个请求的HTTP头部有差异,curl发起的请求有一个HTTP Header

 'Content-Type': 'application/x-www-form-urlencoded'

其它都没有什么不同,怀疑是Flask本身再处理的时候,对POST请求数据解析的时候出的问题。

跟踪代码

app.run 执行后,就可以接受HTTP请求,通过werkzeug.WSGIRequestHandler调用app.__call__, Flask会初始化AppContextRequestContext,查看 flask.ctx.RequestContext.__init__函数,可以看出,RequestContext创建了新的request 对象:

def __init__(self, app, environ, request=None):                                
    self.app = app                                                             
    if request is None:                                                        
        request = app.request_class(environ)                                   
    self.request = request                                                     
    self.url_adapter = app.create_url_adapter(self.request)                    
    self.flashes = None                                                        
    self.session = None                                                        

app.requst_class定义可以在flask.app中看到:

from .wrappers import Request, Response

class Flask(_PackageBoundObject):
    ...
    ...
    request_class = Request

再跟踪wrappers.Reqeust就可以查看到request.form的解析过程。

Finally the culprit: werkzeug.formparser.py

def get_parse_func(self, mimetype, options):
    return self.parse_functions.get(mimetype)
                                                                            
#: mapping of mimetypes to parsing functions                                   
parse_functions = {                                                            
    'multipart/form-data':                  _parse_multipart,                  
    'application/x-www-form-urlencoded':    _parse_urlencoded,                 
    'application/x-url-encoded':            _parse_urlencoded                  
}

以上代码可以看出,只有HTTP Header中包含multipart/form-data, application/x-www-form-urlencoded, application/x-url-encoded才会正确地解析HTTP POST form数据。

The End

展开阅读全文
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部