如何使用 HAProxy 发送响应而不将请求传递给 Web 服务器
Posted
技术标签:
【中文标题】如何使用 HAProxy 发送响应而不将请求传递给 Web 服务器【英文标题】:How to send a response with HAProxy without passing the request to web servers 【发布时间】:2014-12-20 19:38:02 【问题描述】:由于 CORS(跨域资源共享),服务器正在接收数千个 OPTIONS 请求。现在,每个选项请求都被发送到其中一个服务器,这有点浪费,因为知道 HAProxy 可以在没有 Web 服务器帮助的情况下自己添加 CORS 标头。
frontend https-in
...
use_backend cors_headers if METH_OPTIONS
...
backend cors_headers
rspadd Access-Control-Allow-Origin:\ https://www.example.com
rspadd Access-Control-Max-Age:\ 31536000
但是,要使其正常工作,我需要在 cors_headers 后端指定至少一个实时服务器,并且该服务器仍会接收请求。
如何在不指定任何服务器的情况下在后端处理请求?如何停止将请求传播到服务器,同时将响应发送到浏览器并保持连接处于活动状态?
【问题讨论】:
我也想做同样的事情,你能做到吗? 【参考方案1】:为 HAProxy 2.2 及更高版本编辑:如果您需要支持来源白名单,Lua 脚本现在可以生成整个响应,而无需将请求传递给后端服务器。可以在此处找到带有简单集成说明的示例 Lua 脚本:https://github.com/haproxytech/haproxy-lua-cors
在 HAProxy 1.5.14 中执行此操作的唯一方法是手动触发 503 错误(没有可用于处理请求的服务器)并将错误页面设置为带有自定义 CORS 标头的文件。
backend cors_headers
errorfile 503 /path/to/custom/file.http
file.http
应包含所需的标题和末尾的 2 个空行
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Max-Age: 31536000
Content-Length: 0
Cache-Control: private
<REMOVE THIS LINE COMPLETELY>
这种“方法”有几个限制:
在发送 CORS 标头之前无法检查来源,因此您要么必须拥有允许来源的静态列表,要么必须允许所有来源
缺少动态标题:你不能这样做
http-response set-header Date %[date(),http_date]
或设置Expires
标头。
注意:如果您随着时间的推移动态更新 HTTP 文件,要将更改应用到 HAProxy,您必须重新启动它。它可以是优雅重启或硬重启,在任何一种情况下,新文件都将被加载、缓存并立即提供服务。
【讨论】:
haproxy 2.2 添加了允许设置响应的http-request return
指令。不需要 Lua。【参考方案2】:
好消息,HAProxy 2.2 just introduced“本机响应生成器”功能。它与http-request return
指令配合使用,可用于提供静态文件或文本字符串,包括动态参数。
目标是避免使用errorfile
进行常见的黑客攻击。
利用 2.2 版中引入的另一个指令 (http-after-response
),可以通过以下方式实现 OP 目标:
backend cors_headers
# http-response won't work here as the response is generated by HAP
http-after-response set-header Access-Control-Allow-Origin \
"%[req.hdr(Origin)]"
http-after-response set-header Access-Control-Max-Age "31536000"
http-request return status 200 content-type "text/plain" string "" if TRUE
set-header
和 http-request return
可以根据您的需要使用基于请求标头或来源的if
子句来设置条件(有关示例,请参见文档)。
通过这种技术,标头和响应可以使用变量:
http-request return status 200 content-type "text/plain" \
lf-string "Hello, you are: %[src]"
【讨论】:
这非常接近于解决我试图解决的另一个问题,但我使用的是 haproxy 2.1.7 :(以上是关于如何使用 HAProxy 发送响应而不将请求传递给 Web 服务器的主要内容,如果未能解决你的问题,请参考以下文章
如何将一些信息传递给视图而不将其包含在 URL 中(django 新手)
如何自动将用户信息传递给 Bot Framework 对话实例,而不将其作为显式消息发布在聊天窗口中?