HAproxy:OPTIONS 和 POST 方法的不同 503 错误文件

HAproxy: different 503 errorfile for OPTIONS and POST methods

我们有一个 Web 应用程序使用 ajax 调用不同域上的后端 运行(-> 需要 CORS)。 后端由一个 HAproxy 1.4.22 和多个 Wildflys(OpenShift PaaS 上的运行)组成。如果没有 Wildfly 可用(例如在 "Maintenance" 期间),HAproxy 会为每个请求或配置的错误文件提供 503。到目前为止一切顺利...

Web 应用程序根据被拒绝的后端请求(使用 503)正确可视化 "Maintenance Mode" 是一个问题,因为浏览器首先发送一个 OPTIONS 请求(预检)并且已经得到一个 503 .这最终导致浏览器不会将此状态代码反映到 JavaScript 中执行的 ajax 调用(我们总是得到状态代码 0 作为响应,因为浏览器将其解释为飞行前的致命失败并拒绝任何访问). 这个故事并不新鲜,在 Whosebug 上有很多帖子。

那么如何解决这个问题呢? 我的想法是传递两个不同的错误文件("errorfile" 在 HAproxy 语言中)——一个服务于内容为 "HTTP/1.1 200 OK.... Access-Control-Allow-Origin: *...." 的 OPTIONS 请求以通过浏览器中的预检,然后一个错误文件服务于内容为 "HTTP/1.1 503 ....." 的 POST 请求,让浏览器真正反映 ajax 响应中的状态 503。但是,我无法得到这个 运行.

global
    maxconn     256

defaults
    mode                    http
    log                     global
    option                  httplog
    ...

listen express 127.4.184.2:8080
    acl is_options method OPTIONS
    acl is_post method POST

    errorfile 503 /var/lib/openshift/564468c90c1e66c7f2000077/app-root/runtime/repo/503.http if is_post
    errorfile 503 /var/lib/openshift/564468c90c1e66c7f2000077/app-root/runtime/repo/options.http if is_options

    option httpchk GET /
    http-check expect rstatus 2..|3..|401

    balance leastconn
    server local-gear 127.4.184.1:8080 check fall 2 rise 3 inter 2000 cookie local-564468c90c1e66c7f2000077

我知道这行不通,因为 errorfile 不允许 if <condition> 变体。

我怎样才能实现我想要的行为? 如果有人有其他解决方案来解决这个 "Maintanace Mode" / CORS 问题,我愿意接受任何想法......

提前致谢!

我找到了一个很好的解决方案:

  • 定义两个"backends"(因此将"listen"部分拆分为"frontend"和"backend"
  • "frontend" 部分检查请求方法并使用一个 "backend" 来回答 OPTIONS 请求,并使用一个 "backend" 来回答所有其他请求。
  • 第一个定义的 "backend" 用于用 200 回答所有 OPTIONS 请求:这可以通过错误文件来完成,如果我们没有在本节中列出任何服务器,则此 "backend" 被标记as Down 和 responses 因此 errorfile(我们将 200 发送回 OPTIONS 请求)。
  • 第二个定义的 "backend" 保留在 "real" 后端并响应 - 如果真实服务器出现故障 - 也来自错误文件的内容。
  • 在错误文件中,我们可以添加 CORS headers。


HAproxy.cfg:

global
     maxconn     256

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    maxconn                 128
    ...

frontend balancer
    bind 127.8.155.130:8080
    mode http
    acl is_options method OPTIONS
    use_backend cors_backend if is_options
    default_backend business_backend

backend cors_backend
    errorfile 503 options.http

backend business_backend
    errorfile 503 503.http
    server ...
    server ...


options.http

HTTP/1.1 200 OK
Access-Control-Allow-Headers: Origin, Accept, X-Session_id, Content-Type
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Access-Control-Allow-Methods: HEAD, DELETE, POST, GET, OPTIONS, PUT
Connection: close
[empty line]


503.http

HTTP/1.1 503 Service Unavailable
Cache-Control: no-cache
Access-Control-Allow-Origin: *
Connection: close
[empty line]

还有一个额外的惊喜:此配置由 HAproxy 自动处理所有 OPTIONS 请求 - 即使有 CORS 支持!