Python 为什么Apache/WSGI映射要开始?如何加速烧瓶中的头部?

Python 为什么Apache/WSGI映射要开始?如何加速烧瓶中的头部?,python,http,flask,wsgi,Python,Http,Flask,Wsgi,下面是一个Flask应用程序,可以从命令行或通过Apache/WSGI运行: 导入烧瓶 app=烧瓶。烧瓶(\uuuuu名称\uuuuuuu) 长度=1000000#一百万 @app.route('/',methods=['HEAD']) def head(): 返回“x”*长度#响应正文实际上未发送 @app.route('/',方法=['GET']) def get(): 随机输入 返回“”。为范围(长度)内的x连接(str(random.randint(0,9)) 如果uuuu name

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

导入烧瓶
app=烧瓶。烧瓶(\uuuuu名称\uuuuuuu)
长度=1000000#一百万
@app.route('/',methods=['HEAD'])
def head():
返回“x”*长度#响应正文实际上未发送
@app.route('/',方法=['GET'])
def get():
随机输入
返回“”。为范围(长度)内的x连接(str(random.randint(0,9))
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
app.run()#从命令行
其他:
application=app#通过Apache和WSGI
也就是说,这个应用程序返回一百万个随机数字。GET请求需要花费大量的时间,但是HEAD请求应该能够几乎立即返回。这当然是一个说明性的例子;真正的应用程序将涉及大型响应,这些响应对于GET请求生成速度很慢,但也有预先确定的大小,可以由HEAD请求快速查询。(另一个场景:我试图将请求重定向到预先签名的AmazonS3URL,对于HEAD和GET方法,这些URL的签名必须不同。)

问题#1)当我从命令行运行Flask应用程序时,HEAD请求会按预期激活
HEAD
功能;但是当我通过Apache/WSGI运行它时,它会激活
get
函数。为什么会这样,我如何才能绕过它来获得我想要的行为

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

我的猜测是,这些都是出于善意的尝试,以确保HEAD请求始终与相应的GET一致。因此:

猜测#1)Apache或WSGI正在内部重写HEAD以获取

猜测#2)Flask不信任我手动设置内容长度标题,并使用响应正文的实际长度重写它。。。即使是一个HEAD请求,它实际上应该是空的


我是不是误解了什么?关于如何能够更快地处理HEAD请求的任何建议,理想情况下无需缓慢生成仅用于设置内容长度头的大型响应正文?

要从Flask创建完整响应,您需要执行以下操作:

@app.route('/', methods=['HEAD'])
def head():
    response = Response()
    response.headers.add('content-length', LENGTH)
    return response
Connected to localhost.
Escape character is '^]'.
HEAD / HTTP/1.1
Host: localhost

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
content-length: 1000000
Server: Werkzeug/0.9.4 Python/2.7.6
Date: Sun, 16 Mar 2014 22:59:16 GMT
这将导致如下结果:

@app.route('/', methods=['HEAD'])
def head():
    response = Response()
    response.headers.add('content-length', LENGTH)
    return response
Connected to localhost.
Escape character is '^]'.
HEAD / HTTP/1.1
Host: localhost

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
content-length: 1000000
Server: Werkzeug/0.9.4 Python/2.7.6
Date: Sun, 16 Mar 2014 22:59:16 GMT
这是用标准的runner测试的,没有通过wsgi,但是这不会有什么区别

至于Apache/WSGI强制使用get处理程序,有一些提示说明了为什么会发生这种情况


请参阅:

如前所述,mod_wsgi重新映射HEAD to GET的原因在以下章节中有详细描述:

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


如果您不关心HEAD请求返回的响应头与GET请求返回的响应头不同,从而打破了HTTP RFC指定的HEAD要求,然后,只需确保没有配置Apache输出过滤器,并且您可以随意中断内容,因为mod_wsgi随后不会重新映射请求方法类型。

这太完美了,感谢您向我指出我可能应该自己查找的资源:-)。在您参考的SO链接中,得票最多的答案表明,
make_response
被认为比使用
Resource
更“规范”。。。但我想在这种情况下,这是唯一合适的解决方法,对吗?也许你应该尝试使用
make_response
创建响应,然后再设置标题,因为构造函数可能已经在那里定义了覆盖所提供值的值。Graham,非常感谢你提供的有用的博客文章和这个答案。我查看了我的Apache设置,发现禁用mod_过滤器和mod_deflate并不能解决问题。。。但后来我发现关闭SSL确实起了作用。所以我猜mod_wsgi也将SSL加密视为一个输出过滤器,不信任应用程序匹配HEAD和GET。。。这是对的,还是有其他方法可以在不禁用SSL的情况下获取头部请求?如果mod_wsgi代码检测到任何注册的内容级Apache输出筛选器,它将应用重新映射。因此,任何可以使用或修改内容的过滤器。所以,它不区分过滤器的名称。我可能应该做的是提供一个配置检测器,允许在需要时禁用自动重新映射。是的,我认为这将是一个非常有用的配置选项,谢谢!