python - cgi.FieldStorage 不从 requests.post 读取 json 数据

标签 python json python-2.7 python-requests wsgi

我已经按照 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 数据,所以......

提前致谢

福克斯

最佳答案

------------解决方案------------

只需替换 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 需要表格,但我没有发送……这就是问题的根源。还需要对 app.py 进行一些细微的修改,但事实并非如此,可以轻松调整。

关于python - cgi.FieldStorage 不从 requests.post 读取 json 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32737728/

相关文章:

python - Tkinter 自定义框架不工作

python 从字典中获取唯一值

python - 遍历文件的文件夹并在列中添加值?

python - 将两行字符串打印为一行字符串 Tkinter

java - 如何将java bean传递到jsp页面以供jqQrid使用json显示?

python - 在 Python 2.7 中打印 UTF-8 字符

python - python项目结构是什么

python - 使用 .loc 时的 SettingWithCopyWarning

jquery - 使用 JQuery 的 AJAX POST 请求不进行 urlencode '+'

javascript - 旧 JSON 值已更改