cgi.FieldStorage not reads json data from requests.post

折月煮酒 提交于 2019-12-07 15:43:02

问题


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

and

# 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()

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

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)

everything works fine and FieldStorage looks fine

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

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

Thanks in advance

Phux


回答1:


--------------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}

With this

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 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.



来源:https://stackoverflow.com/questions/32737728/cgi-fieldstorage-not-reads-json-data-from-requests-post

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!