本文介绍了cgi.FieldStorage无法从request.post读取json数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've setup simple server as described in Python Cookbook (ch.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数据

Simple agent sends some json data with python.requests

# 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

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

Unfortunately, it produces errors like this

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数据

Application cannot iterate over the received data and wsgi.FieldStorage doesn't contain MiniFieldStorage fields just raw json data

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

如果我尝试发送这样的数据

If I try to send data like this

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

一切正常,FieldStorage看起来很好

everything works fine and FieldStorage looks fine

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

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

BUT I need to receive json data in the final application, so ...

预先感谢

福克斯

推荐答案

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

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

--------------SOLUTION-------------

Just replace these lines in 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进行一些小的修改,但这不是这种情况,可以轻松进行调整.

cgi.FieldStorage expects form and I don't send one ... and this is the root of the problem. Some slight modification in app.py is also needed, but this is not the case and can be easily adjusted.

这篇关于cgi.FieldStorage无法从request.post读取json数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-27 09:14