为什么 Apache/WSGI 将 HEAD 映射到 GET?如何加快 Flask 中的 HEAD 速度?

2024-02-16

这是一个 Flask 应用程序,可以从命令行或通过 Apache/WSGI 运行:

import flask
app = flask.Flask(__name__)

LENGTH = 1000000                # one million

@app.route('/', methods=['HEAD'])
def head():
    return 'x' * LENGTH         # response body isn't actually sent

@app.route('/', methods=['GET'])
def get():
    import random
    return ''.join(str(random.randint(0,9)) for x in range(LENGTH))

if __name__ == '__main__':
    app.run()                   # from command-line
else:
    application = app           # via Apache and WSGI

也就是说,这个应用程序返回一百万个随机数字。 GET 请求需要花费相当多的时间,但 HEAD 请求应该能够几乎立即返回。这当然是一个说明性的例子;真实的应用程序会涉及大型响应,这些响应对于 GET 请求生成起来很慢,但也具有可以通过 HEAD 请求快速查询的预先确定的大小。 (另一种情况:我尝试将请求重定向到预签名的 Amazon S3 URL,该 URL 必须针对 HEAD 和 GET 方法进行不同的签名。)

问题 #1) 当我从命令行运行 Flask 应用程序时,HEAD 请求会激活head功能符合预期;但是当我通过 Apache/WSGI 运行它时,它会激活get功能。这是为什么,我该如何解决它以获得我想要的行为?

问题#2)为什么我不能返回,而不是为 HEAD 请求创建一个虚拟响应(分配一堆内存)app.make_response('', 200, {'Content-Length':LENGTH})?

我的猜测是,这些是由善意的尝试引起的,目的是确保 HEAD 请求应始终与相应的 GET 一致。所以:

猜测 #1) Apache 或 WSGI 正在内部将 HEAD 重写为 GET。

猜测#2) Flask 不信任我手动设置 Content-Length 标头,并用响应正文的实际长度重写它......即使对于 HEAD 请求,实际上它应该是空的。

我误解了什么吗?有关如何更快地处理 HEAD 请求的任何建议,理想情况下无需缓慢生成仅用于设置 Content-Length 标头的大型响应正文?


正如已经指出的,为什么 mod_wsgi 将 HEAD 重新映射到 GET 的问题在以下内容中得到了很好的描述:

  • http://blog.dscpl.com.au/2009/10/wsgi-issues-with-http-head-requests.html http://blog.dscpl.com.au/2009/10/wsgi-issues-with-http-head-requests.html

特别是,正如该博客文章中所解释的,如果您有一个 Apache 输出过滤器设置,并且因此有可能需要从您的 WSGI 应用程序中查看针对同一 URL 的 GET 或 HEAD 的相同输出,那么 mod_wsgi 将不相信您的应用程序做了正确的事情,并将重新映射 HEAD 到 GET 以确保 Apache 输出过滤器正常工作。

如果您不关心 HEAD 请求返回的响应标头与 GET 请求的响应标头不同,从而违反了 HTTP RFC 指定的 HEAD 要求,那么只需确保您没有配置 Apache 输出过滤器你可以随意破坏,因为 mod_wsgi 不会重新映射请求方法类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Apache/WSGI 将 HEAD 映射到 GET?如何加快 Flask 中的 HEAD 速度? 的相关文章

随机推荐