【问题标题】:Can a WSGI middleware modify a request body and then pass it along?WSGI 中间件可以修改请求主体然后将其传递吗?
【发布时间】:2015-07-24 22:51:54
【问题描述】:

我正在尝试编写一个中间件,当它在正文中找到“_method”参数时,它将 POST 请求重写为不同的方法。网上有人写了这段代码:

from werkzeug import Request

class MethodRewriteMiddleware(object):
    def __init__(self, app, input_name='_method'):
        self.app = app
        self.input_name = input_name

    def __call__(self, environ, start_response):
        request = Request(environ)

        if self.input_name in request.form:
            method = request.form[self.input_name].upper()

            if method in ['GET', 'POST', 'PUT', 'DELETE']:
                environ['REQUEST_METHOD'] = method

        return self.app(environ, start_response)

据我了解,它会解析表单,检索可能的“_method”参数,如果找到并列入白名单,它将覆盖当前方法。它适用于 DELETE 请求,并且可以毫无问题地重写该方法。但是,当我尝试发送一个常规的、非重写的 POST 时,这个中间件会使整个应用程序挂起。我最好的猜测是,由于我在中间件中访问了主体,因此主体不再可用于应用程序,因此它永远挂起。但是,这似乎不会影响重写的请求,因此代码最深的代码路径(检查白名单)可以正常工作,但其他代码路径会以某种方式破坏/阻止请求。

我认为这无关紧要,但我正在将此中间件安装在 Flask 应用之上。

编辑:我认为尝试从 Flask 中的处理程序访问 request 是阻塞的。 Flask 是否在内部使用互斥锁或类似的东西?

我什至不确定如何调试它。

【问题讨论】:

  • 尝试使用 from flask import request 并使用烧瓶请求对象
  • 您可以通过不使用 werkzeug 来验证您的假设,而是自己根据环境编写相关的查询字符串解析。这应该不难(cgi-module 有帮助),然后你可以确定你没有接触到身体。或者更好的是,使用 shallow-parameter 来请求。顺便说一句,您的问题具有误导性,因为对此的唯一答案是“是的,当然”。你可以在 WSGI 中对传递的参数做任何你想做的事情,如果你在传递它们(或完全新奇的)时仍然符合 WSGI - 对你有好处。您关心的只是 werkzeug 的参与。

标签: python python-3.x wsgi


【解决方案1】:

environ 是一个带有 wsgi.input 键的字典,它是一个流对象。执行您要查找的操作的手动方法是读取数据,进行任何更改,然后创建一个新字符串来替换 environ 字典中的旧流。下面的示例(没有任何错误处理或其他重要内容)允许您使用请求正文:

def __call__(self, environ, start_response):
    body = environ['wsgi.input'].read()
    ... do stuff to body ...
    new_stream = io.ByteIO(modified_body)
    environ['wsgi.input'] = new_stream
    return self.app(environ, start_response)

【讨论】:

  • 如果请求内容的大小非常大,这将耗尽内存使用。处理此问题的 WSGI 组件库会更智能地执行此操作,如果超过一定大小,会将内容写入文件,然后将类似对象的文件传递给该文件。使用已经执行此操作的现有库之一要好得多。我知道 Paste 或 WebOb 有它的用处,但 Werkzeug 也可以。
猜你喜欢
  • 1970-01-01
  • 2022-09-24
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 2015-07-01
  • 2011-03-17
  • 2015-08-13
  • 1970-01-01
相关资源
最近更新 更多