【问题标题】:Print raw HTTP request in Flask or WSGI在 Flask 或 WSGI 中打印原始 HTTP 请求
【发布时间】:2014-10-17 11:33:38
【问题描述】:

我正在调试我构建的微控制器,它逐行编写原始 HTTP 请求。我正在使用 Flask 作为我的后端,我希望看到以这种格式显示的整个请求:

GET / HTTP/1.1
Content-length: 123
User-agent: blah
...

我知道 Flask 是基于 WSGI 的。有没有办法让它与 Flask 一起工作?

【问题讨论】:

    标签: python flask wsgi


    【解决方案1】:

    是的,Flask 是一个 WSGI 应用程序,因此将您的应用程序包装在一个记录请求的额外层中是微不足道的:

    import pprint
    
    class LoggingMiddleware(object):
        def __init__(self, app):
            self._app = app
    
        def __call__(self, env, resp):
            errorlog = env['wsgi.errors']
            pprint.pprint(('REQUEST', env), stream=errorlog)
    
            def log_response(status, headers, *args):
                pprint.pprint(('RESPONSE', status, headers), stream=errorlog)
                return resp(status, headers, *args)
    
            return self._app(env, log_response)
    

    这定义了一个中间件来包装您的 Flask 应用程序。优点是它完全独立于 Flask 运行,让您可以未经过滤地了解输入内容和输出内容。

    如何应用中间件取决于您使用的确切 WSGI 服务器;请参阅您的 WSGI 服务器文档。

    使用内置服务器 (app.run()) 运行 Flask 时,请执行以下操作:

    if __name__ == '__main__':
        app.wsgi_app = LoggingMiddleware(app.wsgi_app)
        app.run()
    

    app.wsgi_app wrapping dance 将LoggingMiddleware 放置在 Flask WSGI 应用程序周围。

    输出到wsgi.error 流;最终的结果取决于您的 WSGI 服务器; mod_wsgi 将其放入您站点的 Apache 错误日志中,捆绑的 Flask 服务器将其打印到 stderr

    【讨论】:

    • 我怎样才能得到这个解决方案的请求内容呢?
    • @ArthurColombiniGusmão:你确定要这样做吗?身体可能非常大。您还必须使用 stream,它就像一个只能读取一次的文件,然后必须为下一个 WSGI 组件提供一个新的流来替换它。 env['wsgi.input'] 是流,您也许可以将数据复制到tempfile.SpooledTemporaryFile() object,对那个文件做一些事情,然后回到开始并设置env['input.stream'] 指向它。
    • 感谢@Martijn Pieters!这可能不是最好的选择。我的目标是创建一个规范的 sn-p 来快速包装 Flask 应用程序,以便于调试(在受控环境中)。有时,通过使用这样的中间件来调试与 REST API 接口的代码似乎更容易,但可能我在现有解决方案中缺少。
    【解决方案2】:

    使用flask,您可以访问包含所有HTTP详细信息的请求对象:

    from flask import request
    
    @app.route('/')
    def index():
        print(request.headers)
    

    【讨论】:

    • 这仅打印标题,而不是指定的all the HTTP details。使用请求的其他属性也无济于事(例如数据、表单、值等)。要完整打印 HTTP 请求,围绕@martinpieters 的答案中建议的 WSGI 进行包装是可行的方法。
    • 这不是答案。
    【解决方案3】:

    假设你想要完整的细节,

    还有另一种方法

    @app.route('/')
    def index():
        print request.__dict__
        #this prints all variables in `dict` format including `headers`
    

    【讨论】:

    • 那行不通。 headers 甚至不是钥匙; environ 键包含不同的东西,包括标题,但肯定不是完整的原始请求。
    • 实际上这似乎有效。当我在导入pprint 后执行pprint.pformat(request.__dict__, depth=5)) 时,我看到environ 是为我打印的第一个键。
    【解决方案4】:

    为什么不呢?

    from flask import Flask, request
    
    app = Flask(__name__)
    
    @app.before_request
    def log_request():
        app.logger.debug("Request Headers %s", request.headers)
        return None
    
    # The remaining application code.
    

    我已经使用了标头,但是您可以使用相同的方法来打印任何请求属性。文档在这里:http://flask.pocoo.org/docs/0.12/api/#flask.Request

    您还需要将 FLASK_DEBUG=1 设置为 Flask.logger.debug 才能工作,这很好,因为您可以在生产中禁用它。

    问候,

    【讨论】:

      【解决方案5】:

      你可能想要类似的东西

      print(request.headers)
      print(request.data)
      print(request.args)
      print(request.form)
      print(request.endpoint)
      print(request.method)
      print(request.remote_addr)
      

      【讨论】:

        【解决方案6】:

        这不使用烧瓶,但设置socket echo server 相当简单。

        import socket
        
        host = ''
        port = 8888
        backlog = 5
        size = 1024
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((host,port))
        s.listen(backlog)
        while 1:
            client, address = s.accept()
            data = client.recv(size)
            if data:
                client.send(data)
            client.close()
        

        【讨论】:

          【解决方案7】:

          如果您使用的是记录器,我发现这很有用

          https://docs.python.org/3/library/pprint.html#pprint.pformat

          from pprint import pformat
          import requests
          log.debug(pformat(request.headers))
          

          【讨论】:

          • 谢谢。我试过这个并没有看到与repr(request.headers)的区别。你能详细说明一下吗?
          猜你喜欢
          • 2014-01-06
          • 2012-03-28
          • 1970-01-01
          • 1970-01-01
          • 2021-01-20
          • 2021-12-23
          • 2012-10-26
          • 1970-01-01
          • 2013-03-19
          相关资源
          最近更新 更多