HAproxy: unique error handling for OPTIONS and POST requests with 503 errorfile

Our Web application utilizes ajax calls to a backend that operates on a different domain, requiring CORS. The backend setup includes an HAproxy 1.4.22 along with multiple Wildflys running on the OpenShift PaaS. During times when a Wildfly instance is unavailable (e.g., during maintenance), HAproxy responds with a 503 error to every request or serves the configured errorfile.

However, this poses a challenge for the Web application to accurately display "Maintenance Mode" based on a rejected backend request (503 error). The browser initially sends an OPTIONS request (preflight) and receives a 503 response, causing the browser to not relay this status code to the ajax call in JavaScript. This results in always receiving a status code of 0 as a response, as the browser interprets it as a fatal preflight failure and restricts access.

To address this issue, I propose implementing two distinct errorfiles in HAproxy - one to handle OPTIONS requests with a content of "HTTP/1.1 200 OK.... Access-Control-Allow-Origin: *...." to pass the preflight check in the browser, and another errorfile for processing POST requests with a content of "HTTP/1.1 503 ....." to ensure the browser accurately reflects the 503 status in the ajax response. However, I have encountered difficulties in implementing this solution.

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

It is important to note that this approach is limited by the constraints of the errorfile directive not supporting the if <condition> syntax.

How can we achieve the desired behavior? If anyone has alternate solutions to address the "Maintenance Mode" and CORS challenge, we are open to suggestions and ideas.

Thank you in advance!

Answer №1

I devised a clever solution:

  • Split the "listen" section into "frontend" and "backend" to define two separate "backends."
  • The "frontend" section checks for the request method and routes OPTIONS requests to one "backend" and all other requests to another.
  • The first "backend" handles all OPTIONS requests by sending a 200 response, using an errorfile to do so.
  • The second "backend" acts as the primary backend and also serves the content of an errorfile when the real servers are down.
  • The errorfiles include the necessary 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]

This configuration handles OPTIONS requests autonomously with CORS support in HAproxy.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What steps are involved in setting up role-based authentication using Node.js?

Essentially, I am looking for a way for nodeJS to determine if the user logging in through the login page is an admin or not. If they are an admin, they should be directed to the admin page; if not, they should be sent to a different page. Currently, I ha ...

What is the best way to integrate Bootstrap 5 with Next.js?

After adding Bootstrap to my project with npm install bootstrap, I included the style in /pages/_app.js like this: import 'bootstrap/dist/css/bootstrap.css'; export default function App({ Component, pageProps }) { return <Component {...pag ...

Clickable link in popup window using fancybox

When I try to use fancybox to open an iframe and scroll to an anchor tag, it works perfectly in IE but not consistently in other browsers. It stops at a different place than the anchor. I suspect the issue may be related to JavaScript based on information ...

What advantages does KnockoutJS offer over AngularJS?

Can KnockoutJS offer a unique feature that rivals or exceeds those of AngularJS? ...

Dealing with Sideways Overflow Using slideDown() and slideUp()

Attempting to use slideUp() and slideDown() for an animated reveal of page elements, I encountered difficulty when dealing with a relatively positioned icon placed outside the element. During these animations, overflow is set to hidden, resulting in my ico ...

Creating seamless shading effects using three.js with Blender integration

When I import a Blender scene into a three.js environment, the curved faces appear flat. Is there a method to ensure that these surfaces remain smooth as intended? Despite calculating vertex normals and activating the smoothShaded option, the issue persis ...

"Here's a cool trick: A guide on dynamically inserting a value into {% url tag %} using JavaScript within

Incorporating leaflet JS into a Django template, the aim is to display markers on a map where latitude and longitude are sourced from a queryset. Sending the queryset through views and utilizing the Django template language within <script> tags seeme ...

Can a directive be designed to function as a singleton?

Our large single page app includes a directive that is utilized in various locations across the page, maintaining its consistent behavior and appearance each time. However, we are experiencing an issue with this directive due to the ng-repeat it contains, ...

Getting rid of the backslash from a JSON object in an Axios POST request

Question regarding adding a reverse slash to a JSON file when making an Axios post request. Despite using the replace function, the backslash remains in the final output. axios .post( "https://test-manager/backend", { ...

Should I use multiple AJAX requests or load all location data at once for autocomplete in a UI design?

In my application, there is a text box that allows users to choose a location using UI autocomplete. There are approximately 10,000 valid locations from which the user must make a selection. Two different approaches have been implemented for the autocomple ...

Not successfully integrating an angular component

In my Angular application, I am working on creating a new component and injecting it into the app. Below is the code for the angular component: (function(angular) { 'use strict'; angular.module('some.someModule', ['bm.component.t ...

I am experiencing issues with the button click functionality in my Google extension

Greetings! I am currently developing a Chrome extension that will automatically redirect to my website and fill in the password. However, I am facing an issue with submitting the button click event. // Here is my manifest.json code { "name": "z", "v ...

Testing with Phantom/Casper in a browser-based environment

Currently, I am utilizing Casper for UI testing on websites. My main concern is regarding the compatibility testing in various browsers such as IE, Chrome, and Firefox using Casper. If this cannot be achieved with Casper, I am open to alternative methods ...

What causes the syntax error when attempting to delete using ng-init in a straightforward manner?

Take a look at this short code snippet (jsfiddle): <div ng-app="App" ng-init="foo={a: 20}; delete foo['a']"> </div> This causes a syntax error in both Firefox and Chrome browsers. But why? The syntax error states, "Token 'fo ...

Issue with bookmarklet compatibility on mobile browsers like iOS and Android

Here is the bookmarklet code I have: javascript:(function(e,a,g,h,f,c,b,d){if(!(f=e.jQuery)||g>f.fn.jquery||h(f)){c=a.createElement("script");c.type="text/javascript";c.src="cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js";c.onload=c.onreadystate ...

Using jquery to transition an image to fade out and then reappear in a different position

There is an image in a div with the highest z-index. Upon clicking on something, the image should fade out and then fade in at a specified position below another image with the class "aaa". The current approach involves using jQuery to fade out the image ...

Difficulty Sorting Dates in Material UI DataGrid

I have a DataGrid in Material UI, and one of my columns displays dates. Following the guidance from the Material UI documentation, I have set the type to "date" in the column array: { field: "submittedAt", headerName: "Submitted", minWidth: 150, flex: 2, t ...

Searching DynamoDB in node.js using mapped items

In my DynamoDB table, I am trying to retrieve all Items where the Review.ID matches 123. Item: { id: 1, review: { Id: 123, step1: 456, step2: 789, step3: 1234, }, // Add more items here }, Item: { id: 2, review: { Id: 123 ...

Divide the string by spaces

One of the challenges I am facing involves a textarea where users can input messages. The goal is to split the message into an array of words after detecting an '@' symbol, and then search for specific words in that array such as @person1 and @pe ...

What are the steps for making Ajax calls?

I have been working on a Wikipedia viewer for my freecodecamp project. However, I am facing issues with the AJAX request as it keeps failing every time without returning any results. var url, value; $(document).ready(function() { $("button").on("click ...