问题
We have a Web application using ajax calls to a backend running on different domain (-> CORS needed). The backend consists of a HAproxy 1.4.22 and then multiple Wildflys (running on OpenShift PaaS). In case no Wildfly is available (e.g. during "Maintenance"), HAproxy serves 503 to every request or the configured errorfile. So far so good...
This is a problem for the Web application to properly visualise "Maintenance Mode" according to a rejected backend request (with 503), because the browser first sends an OPTIONS request (preflight) and gets already a 503 to it. This ends up that the Browser does not reflect this status code to the performed ajax call in JavaScript (we get always status code 0 as response because the browser interpret it as fatal failure of preflight and denies any access). This story is not new and there are many posts at stackoverflow.
So how to solve this problem? My idea is to deliver two different errorfiles ("errorfile" in HAproxy language) - one serving OPTIONS requests with content "HTTP/1.1 200 OK.... Access-Control-Allow-Origin: *...." to pass the preflight check in the browser, then one errorfile serving the POST requests with content "HTTP/1.1 503 ....." to let the browser really reflect the status 503 in the ajax response. However, I am not able to get this running.
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
I understand that this cannot work because errorfile does not allow the if <condition>
variant.
How can I achieve my wished behaviour? And if someone has another solution to solve this "Maintanace Mode" / CORS problem, I am open for any idea...
Thanks in advance!
回答1:
I found a good solution:
- define two "backends" (therefore split the "listen" section into "frontend" and "backend"
- The "frontend" section checks for the request method and uses one "backend" to answer OPTIONS request and one "backend" to answer all others.
- The first defined "backend" is used to answer all OPTIONS requests with 200: This can be done with an errorfile and if we do not list any server in this section, this "backend" is marked as Down and responses therefore the errorfile (in which we send 200 back to the OPTIONS request).
- The second defined "backend" stays for the "real" backend and responds - in case the real servers are down - also the content from an errorfile.
- In the errorfiles, we can add the 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]
There is one additional adventage: This configuration serves all OPTIONS requests autonomeously by HAproxy - even with CORS support!
来源:https://stackoverflow.com/questions/34022378/haproxy-different-503-errorfile-for-options-and-post-methods