I used this article to document a pit I encountered in my work today with HTTP cross-domain and OPTION requests.

The scenario is that I need to use JavaScript to consume a service deployed on a server deployed on domain B in a Web application deployed on domain A. I also developed the service on domain B, so I added domain A to the header file of the HTTP response structure of the service, allowing JavaScript code on domain A to AJAX access the service on domain B.

The service on domain B is a Servlet that allows domain A to be accessed in a single line:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// do business logic

         response.setHeader("Access-Control-Allow-Origin".Domain name "a");

}
Copy the code

I make a service request using AJAX in the Web application of domain A:

After execution, the popup window for 200 is not displayed.

Request Header field Authorization is not allowed by access-Control-allow-headers in preflight response.

Check Chrome developer tools to find that the domain b service has been successfully executed, and does return 200 Status code.

And I have observed from Chrome Developer Tools that the browser has successfully received a request from domain B.

So what was the mistake? Request Header field Authorization is not allowed by access-Control-allow-headers in preflight response I googled it and found some friends with the same problem:

1. How to troubleshoot AXIOS Request header field content-type is not allowed by access-Control-allow-headers in preflight response?

Website Address:www.cnblogs.com/caimuqing/p…

This friend’s solution:

response.setHeader("Access-Control-Allow-Origin"."*");

response.setHeader("Access-Control-Allow-Credentials"."true");

response.setHeader("Access-Control-Allow-Methods"."*");

response.setHeader("Access-Control-Allow-Headers"."Content-Type,Access-Token");

response.setHeader("Access-Control-Expose-Headers"."*");

if (request.getMethod().equals("OPTIONS")) {

     HttpUtil.setResponse(response, HttpStatus.OK.value(), null);

     return;

}
Copy the code

But I tried it and it still didn’t work in my scenario because in my example the server already returned the HTTP 200 status code for OPTIONS requests.

2. Many friends in this Stackoverflow post offer their own solutions.

Stackoverflow.com/questions/4…

I tried them all, and none of them worked in my scene.

So I looked up a document from Mozilla: HTTP Access Control (CORS)

Developer.mozilla.org/zh-CN/docs/…

In some cases, the browser must first issue a “Preflight” to the server to see if the server will allow the actual request before issuing a “Preflight request.” The “precheck request” mechanism is used to avoid cross-domain requests having an unexpected impact on the server’s user data.

So which requests count as “requests to precheck”? This Mozilla document is very clear:

Precheck requests should be sent first when any of the following conditions are met:

  • Any of the following HTTP methods are used:
  • PUT
  • DELETE
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH
  • A header field other than the header field set that is safe for CORS was set artificially. The set is:
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (but note the additional requirements below)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width
  • The value of the content-type is not one of the following:
  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

I checked my code again because I added a header for Basic Authentication in the HTTP request with xhr.setrequestheader (“Authorization”, “Base64 encoding for username: password”). This forces the request to be a “pre-checked request”, hence the sending of the OPTION request.

I’ll comment it out now:

401 Unauthorized error:

However, no precheck request OPTION was issued, and the request type became the POST I expected.

But now we’re in a paradoxical position: If you add Basic Authentication to the request header, The error message Request Header field Authorization is not allowed by access-Control-allow-headers in preflight response is displayed. If you delete this option, the 401 Unauthorized error is returned, although the precheck request is avoided.

So I switched to a different authentication method and finally achieved the desired cross-domain request, printing out the response from the service of domain B in my domain A front-end application.

I used form authentication, which did not cause the request to be a “pre-checked request,” so it worked.


var formData = new FormData();

formData.append('sap-client'."001");

formData.append('sap-user'."Username");

formData.append('sap-password'."User password");

var request = new XMLHttpRequest();

request.open("POST"."Url of domain B".false);

request.send(formData);

alert("response: " + request.responseText);
Copy the code

I hope my experience of stepping on pits is helpful.

For more of Jerry’s original technical articles, please follow the public account “Wang Zixi” or scan the following QR code: