Bri*_*ian 13 ajax haproxy cors preflight
通过我的NGinx设置,我能够拦截来自ajax预检的OPTIONS请求,并使用正确的CORS标头和200响应进行响应,以便请求可以继续进行.我正在尝试将我的前端代理合并到HAProxy中,并且在解决这个难题时遇到了一些问题.
我的特殊问题是,当有服务器能够正确响应OPTIONS请求时,我能够添加正确的CORS选项,但是当发出预检请求时,一些后端无法处理/响应405错误.我的haproxy.cfg包含以下用于添加标题的行:
capture request header origin len 128
http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if { capture.req.hdr(0) -m found }
rspadd Access-Control-Allow-Credentials:\ true if { capture.req.hdr(0) -m found }
rspadd Access-Control-Allow-Headers:\ Origin,\ X-Requested-With,\ Content-Type,\ Origin,\ User-Agent,\ If-Modified-Since,\ Cache-Control,\ Accept if { capture.req.hdr(0) -m found }
rspadd Access-Control-Allow-Methods:\ GET,\ POST,\ PUT,\ DELETE,\ OPTIONS if { capture.req.hdr(0) -m found }
rspadd Access-Control-Max-Age:\ 1728000 if { capture.req.hdr(0) -m found }
Run Code Online (Sandbox Code Playgroud)
解决方案:
当您从客户端的请求设置所有正确的标头时,如何在不将请求传递给Web服务器的情况下使用HAProxy发送响应,但不是动态的,这不是理想的解决方案.
任何帮助,将不胜感激!
小智 5
你可以使用Lua,但你需要USE_LUA通过检查来确保构建HAproxy haproxy -vv.
这是一个示例配置,我自己没有尝试过,但它会让你知道你可以做什么:
# haproxy.cfg
global
lua-load cors.lua
frontend foo
...
http-request use-service lua.cors-response if METH_OPTIONS { req.hdr(origin) -m found } { ... }
# cors.lua
core.register_service("cors-response", "http", function(applet)
applet:set_status(200)
applet:add_header("Content-Length", "0")
applet:add_header("Access-Control-Allow-Origin", applet.headers["origin"][0])
applet:add_header("Access-Control-Allow-Credentials", "true")
applet:add_header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Origin, User-Agent, If-Modified-Since, Cache-Control, Accept")
applet:add_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
applet:add_header("Access-Control-Max-Age", "1728000")
applet:start_response()
end)
Run Code Online (Sandbox Code Playgroud)
基于anine.io的出色回答,我提出了以下解决方案,该解决方案可以定义允许的来源列表,并且还Acccess-Control-Allow-Origin为所有HTTP请求添加缺少的标头。anine.io的回答仅显示了CORS的预检,但未考虑正常的请求。
在全局部分中haproxy.cfg加载cors.lua文件(必要时修改路径)
global
lua-load /usr/local/etc/haproxy/cors.lua
Run Code Online (Sandbox Code Playgroud)
将CORS配置添加到您的前端定义
frontend http-in
# CORS configuration
# capture origin HTTP header
capture request header origin len 128
# add Access-Control-Allow-Origin HTTP header to response if origin matches the list of allowed URLs
http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if !METH_OPTIONS { capture.req.hdr(0) -m reg -f /usr/local/etc/haproxy/cors-origins.lst }
# if a preflight request is made, use CORS preflight backend
http-request use-service lua.cors-response if METH_OPTIONS { capture.req.hdr(0) -m reg -f /usr/local/etc/haproxy/cors-origins.lst }
Run Code Online (Sandbox Code Playgroud)
创建一个名为的文件cors.lua,并将其存储在上面指定的路径下。该文件包含CORS的预检信息,如果没有充分的理由,请不要限制Method或Headers,因为您必须在中的CORS配置中定义的ACL中包括有关方法或标头的任何限制haproxy.conf。注:目前的浏览器不支持通配符*的Access-Control-Allow-Methods头。该cors.lua文件应包含以下内容
core.register_service("cors-response", "http", function(applet)
applet:set_status(200)
applet:add_header("Content-Length", "0")
applet:add_header("Access-Control-Allow-Origin", applet.headers["origin"][0])
applet:add_header("Access-Control-Allow-Credentials", "true")
applet:add_header("Access-Control-Allow-Headers", "*")
applet:add_header("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS")
applet:add_header("Access-Control-Max-Age", "1728000")
applet:start_response()
end)
Run Code Online (Sandbox Code Playgroud)
创建一个名为的文件cors-origins.lst,并将其存储在CORS配置中您在上面指定的路径下。该文件应包含正则表达式(或仅包含简单字符串)。如果客户端发送了Origin标头,则将针对这些正则表达式进行验证,并且只有当它们匹配时,cors.lua才会返回CORS Preflight from (对于HTTP OPTIONS请求),或者将Access-Control-Allow-Origin带有客户端请求标头的值添加到响应。的内容示例cors-origins.lst可能是
example.com
localhost.*
.*\.mydomain\.com:[8080|8443]
Run Code Online (Sandbox Code Playgroud)
使用http://test-cors.org/测试配置。对于GET请求,应该没有CORS Preflight。对于除GET以外的请求,客户端应首先执行CORS Preflight请求(例如HTTP OPTIONS调用),以检查是否允许使用预期的方法,标头和授权。
有关CORS的更多详细信息,请参见HTTP访问控制(CORS)。
| 归档时间: |
|
| 查看次数: |
9148 次 |
| 最近记录: |