How to Fix CORS Error Policy in SpringBoot and React

When developing web applications, you’ll often run into CORS (Cross-Origin Resource Sharing) errors when your frontend (React JS) and backend (Spring Boot) are running on different origins (i.e., different ports or domains). This happens because modern browsers block requests made across different domains for security reasons unless the server allows it. In this article, we will address a common CORS error you might face while working with React JS and Spring Boot.

CORS Error in React JS and Spring Boot Integration

You may encounter the following error when calling a DELETE service from React JS to Spring Boot backend using Axios:

Access to XMLHttpRequest at 'http://localhost:8080/testdelete' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This error occurs because the server (Spring Boot) hasn’t been configured to allow cross-origin requests from your React app, which is running on http://localhost:3000. The browser is blocking this request due to the absence of the appropriate headers in the response.

Setting up CORS in Spring Boot

To resolve this issue, we need to configure Spring Boot to allow cross-origin requests. Here’s how you can handle this in the Spring Boot application.

Spring Boot Controller Code with CORS Configuration

In your Spring Boot controller, you can add the @CrossOrigin annotation to allow requests from specific origins. For example:

@CrossOrigin(origins = "http://localhost:3000", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.OPTIONS})
@RestController
public class TestDelete {

@DeleteMapping("/testdelete")
public ResponseEntity<Void> deleteData(@RequestBody Data data) throws Exception {
// Your logic to delete data
return ResponseEntity.noContent().build();
}
}

Explanation of the @CrossOrigin Annotation:

  • origins: Specifies the allowed origin(s) (in this case, http://localhost:3000 where your React app is running). You can specify a list of origins if you have more than one frontend URL.
  • methods: Defines which HTTP methods are allowed. We’ve listed GET, POST, DELETE, and OPTIONS because you may use them in your application.

The @CrossOrigin annotation tells Spring Boot to include the necessary CORS headers in the response, such as:

  • Access-Control-Allow-Origin: Specifies which origins are allowed to access the resource.
  • Access-Control-Allow-Methods: Specifies which HTTP methods are allowed for cross-origin requests.
  • Access-Control-Allow-Headers: Specifies which headers are allowed in the request.

React JS Code with Axios

Your React JS code is making a DELETE request to the backend, but you’re manually setting some of the CORS-related headers in the Axios request. While the backend should already handle the CORS headers properly (via @CrossOrigin), you don’t need to set Access-Control-Allow-Headers, Access-Control-Allow-Origin, and Access-Control-Allow-Methods in the Axios request. The browser will handle them automatically.

Here’s the updated React code:

 axios({
method: 'DELETE',
url: `http://localhost:8080/testdelete`,
data: data,
headers: {
'Content-Type': 'application/json',
}
})

Key Points:

  • No need to manually set CORS headers in the request: The CORS headers (Access-Control-Allow-Origin, etc.) should be managed by the Spring Boot server.
  • Correct usage of @CrossOrigin: Ensure that the @CrossOrigin annotation is applied at the method level (as shown) to allow the DELETE method.

Additional Steps to Ensure Correct CORS Setup

Global CORS Configuration

If you want to configure CORS globally across your entire Spring Boot application (for all controllers), you can do this by creating a WebMvcConfigurer bean. This way, you don’t have to add @CrossOrigin on each individual controller or method.

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "DELETE", "OPTIONS");
}
}

This configuration ensures that all requests from http://localhost:3000 are allowed to access any endpoint in your Spring Boot application.

Using @CrossOrigin at Class Level

You can also apply @CrossOrigin at the class level to apply it to all the methods within that class. This is helpful when you want all endpoints in a specific controller to allow cross-origin requests from a certain origin.

@CrossOrigin(origins = "http://localhost:3000", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.OPTIONS})
@RestController
public class TestDelete {
// All methods in this class will have the CORS configuration
}

React Development Server Proxy Setup

Sometimes, especially during development, it’s a good idea to set up a proxy for React JS to bypass CORS issues without configuring CORS headers in the backend. You can add this to your package.json file in the React app:

"proxy": "http://localhost:8080",

This configuration makes requests from localhost:3000 automatically proxy through to localhost:8080, avoiding CORS issues during development.

Final Thoughts

Now that your CORS error is resolved, you can start adding more functionality to your application. Here are some extra features to try adding:

  • Add Error Handling in React: Improve your frontend by handling errors such as timeouts or failed requests.
axios({
method: 'DELETE',
url: `http://localhost:8080/testdelete`,
data: data,
headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
console.log("Data deleted successfully");
})
.catch(error => {
console.error("Error deleting data:", error);
});
  • Implement Pagination for Data Retrieval: If you’re dealing with large datasets, consider adding pagination to your backend and frontend.
  • Enhance Security with CSRF Protection: CORS is important, but security should also be a priority. Consider enabling CSRF protection to prevent malicious attacks.
  • Optimizing Axios Requests: Use interceptors in Axios to handle common logic for each request, such as adding authentication tokens to the request headers.

Related blog posts