【问题标题】:Accessing POST Data from WSGI从 WSGI 访问 POST 数据
【发布时间】:2010-10-06 13:01:30
【问题描述】:

我似乎无法弄清楚如何使用 WSGI 访问 POST 数据。我在 wsgi.org 网站上尝试了该示例,但没有成功。我现在正在使用 Python 3.0。请不要推荐 WSGI 框架,因为那不是我想要的。

我想弄清楚如何将其放入字段存储对象中。

【问题讨论】:

  • FWIW,此时仍然没有 Python 3.0 的 WSGI 规范,所以你所做的任何事情都可能是浪费精力,因为任何最终的规范更新都可能与任何人尝试实现它的尝试不兼容可能会说 Python 3.0。对于 WSGI 应用程序,最好还是使用 Python 2.X。
  • @GrahamDumpleton 不再是:python.org/dev/peps/pep-3333(我们不要误导像我这样稍后阅读本文的人 - 也可以节省他们的时间)
  • @JermoeJ - 他在 2009 年写了评论,你在 2013 年回复;不要认为他试图误导任何人。 :)

标签: python python-3.x wsgi


【解决方案1】:

我建议你看看一些框架是如何做的。 (我不推荐任何一个,仅以它们为例。)

这是来自Werkzeug的代码:

http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/wrappers.py#L150

调用

http://dev.pocoo.org/projects/werkzeug/browser/werkzeug/utils.py#L1420

这里总结起来有点复杂,所以我不会。

【讨论】:

  • 在 Python 3.0 中仍然无法使用,而这正是我正在寻找的。不过还是谢谢。
  • @FireCrow 看看框架是如何工作的似乎是个好主意。这并不是真正建议一种框架方式。
  • 链接已经失效。
【解决方案2】:
body= ''  # b'' for consistency on Python 3.0
try:
    length= int(environ.get('CONTENT_LENGTH', '0'))
except ValueError:
    length= 0
if length!=0:
    body= environ['wsgi.input'].read(length)

请注意,WSGI 尚未完全针对 Python 3.0 指定,并且许多流行的 WSGI 基础架构尚未转换(或已转换为 2to3d,但未经过适当测试)。 (即使 wsgiref.simple_server 也不会运行。)今天你在 3.0 上做 WSGI 的日子不好过。

【讨论】:

  • 是的,我在让 wsgiref 工作时遇到了问题。我最终实施了补丁。
【解决方案3】:

假设您只是尝试将 POST 数据放入 FieldStorage 对象:

# env is the environment handed to you by the WSGI server.
# I am removing the query string from the env before passing it to the
# FieldStorage so we only have POST data in there.
post_env = env.copy()
post_env['QUERY_STRING'] = ''
post = cgi.FieldStorage(
    fp=env['wsgi.input'],
    environ=post_env,
    keep_blank_values=True
)

【讨论】:

  • 这在 Python 3.0 中不起作用 - wsgi.input 返回字节而不是字符串时存在问题。 :( 我需要一种在 Python 3.0 中执行此操作的方法...
  • 您使用的是什么 WSGI 处理程序?如果我使用内置的 CGIHandler 它对我来说很好。我的本地服务器上有一个文件“post.cgi”,其中pastebin.com/f40849562 的内容运行良好。
  • wsgi.input 是什么io类?如果它是 BufferedIOBase,那么您应该能够将其包装在 TextIOWrapper 中,以便 cgi.FieldStorage 可以使用它。
  • @Mike,我也想过,但从长远来看,这会使其无法正常运行,因为发布数据可以是二进制的(例如,文件)。
  • @Evan,也许我疯了,但您可以将输入包装在 TextIOWrapper 中并扩展 FieldStorage 并覆盖 make_file 方法以返回您自己的包装器一个在写入时编码回二进制数据的文件......如果这不能以更简单的方式完成。您使用的是哪个 WSGI 处理程序?
【解决方案4】:

这对我有用(在 Python 3.0 中):

import urllib.parse

post_input = urllib.parse.parse_qs(environ['wsgi.input'].readline().decode(),True)

【讨论】:

    【解决方案5】:

    我遇到了同样的问题,我花了一些时间研究解决方案。
    包含详细信息和资源的完整答案(因为此处接受的答案在 python3 上对我不起作用,在 env 库等中需要纠正许多错误):

    # the code below is taken from and explained officially here:
    # https://wsgi.readthedocs.io/en/latest/specifications/handling_post_forms.html
    import cgi
    def is_post_request(environ):
        if environ['REQUEST_METHOD'].upper() != 'POST':
            return False
        content_type = environ.get('CONTENT_TYPE', 'application/x-www-form-urlencoded')
        return (content_type.startswith('application/x-www-form-urlencoded' or content_type.startswith('multipart/form-data')))
    def get_post_form(environ):
        assert is_post_request(environ)
        input = environ['wsgi.input']
        post_form = environ.get('wsgi.post_form')
        if (post_form is not None
            and post_form[0] is input):
            return post_form[2]
        # This must be done to avoid a bug in cgi.FieldStorage
        environ.setdefault('QUERY_STRING', '')
        fs = cgi.FieldStorage(fp=input,
                              environ=environ,
                              keep_blank_values=1)
        new_input = InputProcessed()
        post_form = (new_input, input, fs)
        environ['wsgi.post_form'] = post_form
        environ['wsgi.input'] = new_input
        return fs
    class InputProcessed(object):
        def read(self, *args):
            raise EOFError('The wsgi.input stream has already been consumed')
        readline = readlines = __iter__ = read
    
    # the basic and expected application function for wsgi
    # get_post_form(environ) returns a FieldStorage object
    # to access the values use the method .getvalue('the_key_name')
    # this is explained officially here:
    # https://docs.python.org/3/library/cgi.html
    # if you don't know what are the keys, use .keys() method and loop through them
    def application(environ, start_response):
        start_response('200 OK', [('Content-type', 'text/plain')])
        user = get_post_form(environ).getvalue('user')
        password = get_post_form(environ).getvalue('password')
        output = 'user is: '+user+' and password is: '+password
        return [output.encode()]
    

    【讨论】:

      猜你喜欢
      • 2015-07-30
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 2014-03-08
      • 1970-01-01
      • 2014-10-16
      相关资源
      最近更新 更多