skip to Main Content

This issue is bugging me from entire day today. I am not being able to read response body when server (Spring Boot) is sending a 400 BAD REQUEST response.

From the best of my knowledge, the access control headers in the response looks good and client should be allowed to read the body.

Technical details now.

My ReactJs application endpoint is http://localhost:3000/ which I use in browser to access the web app.

Client (ReactJs) application is sending an OPTIONS request (Preflight) first and server is returning 200 OK response with below headers.

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization, content-type
access-control-allow-methods: PUT, GET, HEAD, POST, DELETE, OPTIONS
access-control-allow-origin: http://localhost:3000
Access-Control-Max-Age: 1800
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Tue, 25 Apr 2023 10:24:39 GMT
Expires: 0
Keep-Alive: timeout=60
Pragma: no-cache
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

Now the headers from the response of main POST request:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: close
Content-Length: 101
Content-Type: application/json
Date: Tue, 25 Apr 2023 11:02:33 GMT
Expires: 0
Pragma: no-cache
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=bloc

If I print the response using JSON.stringigy(...) then I get an empty object as {}.

If I print the response object directly. I see it like.
enter image description here

Response tab also appears as blank in Chrome Developer Tools (Network tab)
enter image description here

What I have tried:

  1. In postman, response body is returned properly as expected.
  2. Added a filter to log response from server side just to verify if it is server is actually sending the response. I can see the expected response printed.
  3. Tried Edge. Same issue.
  4. Response Body is properly readable for GET requests as well POST requests as long as response status is 200 OK. I can see the issue is only appearing when server is sending 400 BAD REQUEST response.

Below is my client-side source code. I do not have anything related to cors in my request.

fetch(`${API_ROOT}/xxx/schedule`, {
  method: "POST",
  body: postData,
  headers: {
    Authorization: `Bearer ${context.user.token}`,
    "Content-Type": "application/json",
  },
})
  .then(function (response) {
    console.log(JSON.stringify(response));
    console.log(response);
    if (!response.ok) {
      throw response;
    }
    return response.json();
  })
  .then(function (text) {
    console.log(text);
    toast.success("New record is added successfully.");
  })
  .catch(function (error: ErrorResponse) {        
    toast.error(
      <div>
        Error adding Schedule. <br />
        {error.message}
      </div>
    );
    console.log(["Error adding Schedule.", error]);
  });

Please let me know if more information is required.

2

Answers


  1. It appears that the issue is related to CORS (Cross-Origin Resource Sharing) configuration. The server seems to be configured correctly to allow the client origin, and the preflight OPTIONS request is returning a 200 OK response with the correct headers. However, when the actual POST request is made and returns a 400 BAD REQUEST response, the response body is not being received by the client.

    This is likely due to the fact that the server is not sending the correct CORS headers for a non-200 response. When a non-200 response is returned, the browser looks for the Access-Control-Allow-Origin header in the response, and if it is not present or does not match the client origin, then the browser will not allow the response body to be read.

    To fix this issue, you need to make sure that the server is sending the Access-Control-Allow-Origin header in the response for a non-200 response. You can do this by adding the following code to your Spring Boot application’s configuration:

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowedHeaders("*")
                        .allowCredentials(true)
                        .maxAge(3600);
            }
        };
    }
    

    This code will configure CORS to allow any origin (*) to access the server’s resources, and allow the GET, POST, PUT, and DELETE methods. It will also allow any headers, and enable credentials (i.e. allow cookies) and set the max age to 3600 seconds.

    After adding this configuration, the server should send the Access-Control-Allow-Origin header for a non-200 response, and the client should be able to read the response body.

    Login or Signup to reply.
  2. You have to await the body in the error case, too:

    fetch(`${API_ROOT}/xxx/schedule`, {
      method: "POST",
      body: postData,
      headers: {
        Authorization: `Bearer ${context.user.token}`,
        "Content-Type": "application/json",
      },
    })
      .then(function (response) {
        console.log(JSON.stringify(response));
        console.log(response);
        if (!response.ok) {
          throw response;
        }
        return response.json();
      })
      .then(function (text) {
        console.log(text);
        toast.success("New record is added successfully.");
      })
      .catch(res => res.json())
      .then(function (error: ErrorResponse) {        
        toast.error(
          <div>
            Error adding Schedule. <br />
            {error.message}
          </div>
        );
        console.log(["Error adding Schedule.", error]);
      });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search