代码之家  ›  专栏  ›  技术社区  ›  Phux Gengod

cgi。FieldStorage未从requests.post读取json数据

  •  3
  • Phux Gengod  · 技术社区  · 9 年前

    我已经按照Python Cookbook(第11章)中的描述设置了简单的服务器

    # server.py
    
    import cgi
    
    
    def notfound_404(environ, start_response):
        start_response('404 Not found', [('Content-type', 'text-plain')])
        return [b'Not found']
    
    
    class PathDispatcher:
        def __init__(self):
            self.pathmap = {}
    
        def __call__(self, environ, start_response):
            path = environ['PATH_INFO']
    
            post_env = environ.copy()
            post_env['QUERY_STRING'] = ''
    
            params = cgi.FieldStorage(fp=environ['wsgi.input'], environ=post_env, keep_blank_values=True)
    
            environ['params'] = {key: params.getvalue(key) for key in params}
    
            method = environ['REQUEST_METHOD'].lower()
    
            handler = self.pathmap.get((method, path), notfound_404)
            return handler(environ, start_response)
    
        def register(self, method, path, function):
            self.pathmap[method.lower(), path] = function
            return function
    

    # app.py
    
    def send_json(environ, start_response):
        start_response('200 OK', [('Content-type', 'text/plain')])
    
        params = environ['params']
    
        result = ""
    
        for key, param in params.iteritems():
            result += str(key) + ' :: ' + str(param) + '\n'
    
        yield result.encode('utf-8')
    
    
    if __name__ == '__main__':
        from server import PathDispatcher
        from wsgiref.simple_server import make_server
    
        dispatcher = PathDispatcher()
        dispatcher.register('POST', '/send-json', send_json)
    
        httpd = make_server('', 8080, dispatcher)
        print('Listening on 8080...')
    
        httpd.handle_request()
    

    简单代理使用python.requests发送一些json数据

    # agent.py
    
    import requests
    import json
    
    json_data = {'some': 'data', 'moredata':[{1: 'one'}, {2: 'two'}]}
    
    url = "http://localhost:8080/send-json"
    headers = {'Content-Type': 'application/json'}
    
    r = requests.post(url=url, data=json.dumps(json_data), headers=headers)
    
    print r.text
    

    不幸的是,它会产生这样的错误

    Traceback (most recent call last):
      File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
        self.result = application(self.environ, self.start_response)
      File "/home/phux/PycharmProjects/printoscope_sql_injection/server.py", line 24, in __call__
        environ['params'] = {key: params.getvalue(key) for key in params}
      File "/usr/lib/python2.7/cgi.py", line 517, in __iter__
        return iter(self.keys())
      File "/usr/lib/python2.7/cgi.py", line 582, in keys
        raise TypeError, "not indexable"
    TypeError: not indexable
    127.0.0.1 - - [23/Sep/2015 12:25:17] "POST /initial-scan HTTP/1.1" 500 59
    

    应用程序无法迭代接收的数据和wsgi。FieldStorage不包含MiniFieldStorage字段,仅包含原始json数据

    FieldStorage(None, None, '{"moredata": [{"1": "one"}, {"2": "two"}], "some": "data"}')
    

    如果我尝试这样发送数据

    r = requests.post(url=url, data=json_data)
    

    一切正常,FieldStorage看起来也不错

    FieldStorage(None, None, [MiniFieldStorage('moredata', '1'), MiniFieldStorage('moredata', '2'), MiniFieldStorage('some', 'data')])
    

    但我需要在最终应用程序中接收json数据,所以。。。

    提前感谢

    Phux公司

    1 回复  |  直到 9 年前
        1
  •  0
  •   Phux Gengod    9 年前

    --------------溶液-------------

    只需替换server.py中的这些行

    post_env = environ.copy()
    post_env['QUERY_STRING'] = ''
    
    params = cgi.FieldStorage(fp=environ['wsgi.input'], environ=post_env, keep_blank_values=True)
    
    environ['params'] = {key: params.getvalue(key) for key in params}
    

    用这个

    try:
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    except ValueError:
        request_body_size = 0
    
    request_body = environ['wsgi.input'].read(request_body_size)
    
    params = json.loads(request_body)
    
    environ['params'] = {key: params[key] for key in params}
    

    cgi。FieldStorage需要表单,而我没有发送表单……这是问题的根源。应用程序中的一些轻微修改。py也是需要的,但事实并非如此,可以轻松调整。