HAProxy CORS OPTIONS标头截取设置 [英] HAProxy CORS OPTIONS header intercept setup

查看:520
本文介绍了HAProxy CORS OPTIONS标头截取设置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用NGinx设置,我能够拦截来自ajax预检的OPTIONS请求,并使用正确的CORS标头和200响应进行响应,因此请求可以继续进行.我试图将我的前端代理合并到HAProxy中,并且遇到一些问题,使这一难题得以解决.

With my NGinx setup I was able to intercept OPTIONS requests from ajax preflight and respond with the correct CORS headers and a 200 response so the request could continue onwards. I am attempting to consolidate my frontend proxies into HAProxy and am having some issues getting this piece of the puzzle working.

我的特殊问题是,当服务器能够正确响应OPTIONS请求时,尽管我能够添加适当的CORS选项,但是当预检请求被处理时,一些后端无法处理/响应405错误.发布.我的haproxy.cfg包含以下用于添加标题的行:

My particular issue is that while I am able to add the proper CORS options when there is a server able to respond properly to an OPTIONS request, a few of the backends cannot handle/respond with a 405 error when the preflight request is issued. My haproxy.cfg included the following lines for adding the headers:

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 }

解决方案:

如何当您从客户端请求中设置所有正确的标头时,使用HAProxy发送响应而不将请求传递到Web服务器是可行的,但是它不是动态的,这不是理想的解决方案.

How to send a response with HAProxy without passing the request to web servers works when you set all of the correct headers from a client's request, but is not dynamic which is not an ideal solution.

任何帮助将不胜感激!

推荐答案

基于 anine.io的出色答案我提出了以下解决方案,该解决方案可以定义允许的来源列表,并且还为所有HTTP请求添加缺少的Acccess-Control-Allow-Origin标头. anine.io的回答仅显示了CORS的预兆,但未考虑正常的请求.

Based on the great answer from anine.io I came up with the following solution which allows to define a list of allowed origins and it also adds the missing Acccess-Control-Allow-Origin Header for all HTTP requests. The answer from anine.io only showed the CORS preflight, but didn't consider the normal requests.

haproxy.cfg中,在全局部分中加载cors.lua文件(如有必要,请修改路径)

In haproxy.cfg load the cors.lua file (adapt the path if necessary) in the global section

global
    lua-load /usr/local/etc/haproxy/cors.lua

将CORS配置添加到您的前端定义

Add the CORS configuration to your frontend definition

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 }

创建一个名为cors.lua的文件,并将其存储在您上面指定的路径下.该文件包含CORS的预检信息,如果没有充分的理由,请不要限制方法或标头,因为您必须在haproxy.conf中的CORS配置中定义的ACL中包括有关方法或标头的任何限制. 注意:当前浏览器不支持Access-Control-Allow-Methods标头使用通配符*. cors.lua文件应包含以下内容

Create a file called cors.lua and store it under the path you specified above. The file contains the CORS preflight and if there's no good reason, don't restrict Methods or Headers because you would have to include any restrictions regarding methods or headers in the ACLs defined in the CORS configuration in haproxy.conf. Note: Currently Browsers do not support wildcard * for the Access-Control-Allow-Methods header. The cors.lua file should contain the following content

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)

创建一个名为cors-origins.lst的文件,并将其存储在CORS配置中您在上面指定的路径下.该文件应包含正则表达式(或仅包含简单字符串).如果客户端发送一个Origin标头,则将针对这些正则表达式进行验证,并且只有当它们匹配时,才会返回来自cors.lua的CORS Preflight(对于HTTP OPTIONS请求)或带有原点值的Access-Control-Allow-Origin客户请求的标头将添加到响应中. cors-origins.lst内容的示例可能是

Create a file called cors-origins.lst and store it under the path you specified above in the CORS configuration. The file should contain regular expressions (or just simple strings). If the client sends an Origin header, it will be validated against these regular expressions and only if they match, the CORS Preflight from cors.lua will be returned (for HTTP OPTIONS requests) or the Access-Control-Allow-Origin with the value of the origin header of the client request will be added to the response. An example of the content of cors-origins.lst could be

example.com
localhost.*
.*\.mydomain\.com:[8080|8443]

使用 http://test-cors.org/测试配置.对于GET请求,应该没有CORS Preflight.对于GET以外的请求,客户端应首先执行CORS Preflight请求(例如HTTP OPTIONS调用),以检查是否允许使用预期的方法,标头和授权.

Test the configuration with http://test-cors.org/. For GET requests there should be no CORS Preflight. For requests other than GET, a CORS Preflight request should be done by the client first (e.g. an HTTP OPTIONS call) to check if the intended method, headers and authorization is allowed.

有关更多详细信息,请参见 HTTP访问控制(CORS)关于CORS.

See HTTP access control (CORS) for further details regarding CORS.

这篇关于HAProxy CORS OPTIONS标头截取设置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆