I have a React application based on Typescript which is hosted on my PC. I use Spring gateway to forward requests to another microservice. GET requests are working fine but for POST requests I get:
Access to XMLHttpRequest at ':8080/api/support/tickets/create' 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.
I'm hitting this Spring Cloud Gateway issue:
Spring cloud configuration:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingFactory) {
return builder.routes()
.route("route_id",
route -> route
.path("/api/support/tickets/**")
.filters(f -> f.rewritePath("/api/support/tickets/(?<RID>.*)", "/support/tickets/${RID}"))
.uri("lb://merchant-hub-admin-service")
)
.build();
}
React code:
export async function getTicket(id: string) {
return await axios.get(`${baseUrl}/support/tickets/ticket/${id}`);
}
export async function postTicket(
data: TicketFullDTO
): Promise<AxiosResponse<TicketFullDTO>> {
return await axios.post<TicketFullDTO>(
`${baseUrl}/support/tickets/create`, data);
}
This is caused by buy-in Spring Cloud Gateway:
I tried to implement this workaround:
@Bean
public RoutePredicateHandlerMapping tusRoutePredicateHandlerMapping(FilteringWebHandler webHandler,
RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties,
Environment environment) {
RoutePredicateHandlerMapping routePredicateHandlerMapping = new RoutePredicateHandlerMapping(webHandler,
routeLocator, globalCorsProperties, environment);
routePredicateHandlerMapping.setCorsProcessor(new CrackCorsProcessor());
return routePredicateHandlerMapping;
}
import org.springframework.lang.Nullable;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.DefaultCorsProcessor;
import org.springframework.web.server.ServerWebExchange;
public class CrackCorsProcessor extends DefaultCorsProcessor {
@Override
public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exchange) {
return false;
}
}
But it's not working. Do you know how I can solve this issue?
I have a React application based on Typescript which is hosted on my PC. I use Spring gateway to forward requests to another microservice. GET requests are working fine but for POST requests I get:
Access to XMLHttpRequest at 'http://1.1.1.1:8080/api/support/tickets/create' 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.
I'm hitting this Spring Cloud Gateway issue: https://github./spring-cloud/spring-cloud-gateway/issues/229
Spring cloud configuration:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingFactory) {
return builder.routes()
.route("route_id",
route -> route
.path("/api/support/tickets/**")
.filters(f -> f.rewritePath("/api/support/tickets/(?<RID>.*)", "/support/tickets/${RID}"))
.uri("lb://merchant-hub-admin-service")
)
.build();
}
React code:
export async function getTicket(id: string) {
return await axios.get(`${baseUrl}/support/tickets/ticket/${id}`);
}
export async function postTicket(
data: TicketFullDTO
): Promise<AxiosResponse<TicketFullDTO>> {
return await axios.post<TicketFullDTO>(
`${baseUrl}/support/tickets/create`, data);
}
This is caused by buy-in Spring Cloud Gateway: https://github./spring-cloud/spring-cloud-gateway/issues/2472
I tried to implement this workaround:
@Bean
public RoutePredicateHandlerMapping tusRoutePredicateHandlerMapping(FilteringWebHandler webHandler,
RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties,
Environment environment) {
RoutePredicateHandlerMapping routePredicateHandlerMapping = new RoutePredicateHandlerMapping(webHandler,
routeLocator, globalCorsProperties, environment);
routePredicateHandlerMapping.setCorsProcessor(new CrackCorsProcessor());
return routePredicateHandlerMapping;
}
import org.springframework.lang.Nullable;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.DefaultCorsProcessor;
import org.springframework.web.server.ServerWebExchange;
public class CrackCorsProcessor extends DefaultCorsProcessor {
@Override
public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exchange) {
return false;
}
}
But it's not working. Do you know how I can solve this issue?
Share Improve this question edited Feb 2, 2022 at 23:03 AmerllicA 32.7k17 gold badges144 silver badges167 bronze badges asked Jan 9, 2022 at 1:32 Peter PenzovPeter Penzov 1,618156 gold badges500 silver badges907 bronze badges 11- Have you configured the gateway for CORS? From the Github link it looks like there are some workarounds to set the allowed methods. – GenericUser Commented Jan 9, 2022 at 2:04
- Yes, I tried but it's not solving the issue. – Peter Penzov Commented Jan 9, 2022 at 2:05
- What response headers does postman or something similar show on a post request? – kevinSpaceyIsKeyserSöze Commented Jan 9, 2022 at 7:18
- See this picture: ibb.co/gmQBYvW – Peter Penzov Commented Jan 9, 2022 at 8:15
-
I... it could be that I'm blind, but I don't see any
Access-Control-Allow-Origin
headers... – Elias Commented Jan 30, 2022 at 14:46
2 Answers
Reset to default 3 +250Actually, CORS is a browser feature and you can disable it in the development area.
The browser should call an OPTIONS for non-matched URLs (website URL & API URL) when these two aren't matched, the browser must call an OPTIONS call to Backend API to get allowed to continue, for production if your website URL and API are not matched you should ask your Backend or DevOps guys to settle it up but for the development area there a couple of things you can do:
if you are using CRA, the previous answer can help you.
if you are using custom configuration and you have a Webpack config file, add this line to your Webpack and it can help you:
module.exports = { devServer: { proxy: 'http://1.1.1.1:8080', },
another cute way is directly disabling security in your Chrome to have an easy development, put these mands in their related OS and run, you will run a new instance of chrome without security (without OPTIONS call):
## macOS open -na Google\ Chrome --args --user-data-dir=/tmp/temporary-chrome-profile-dir --disable-web-security --disable-site-isolation-trials
## windows chrome.exe --disable-web-security
## linux google-chrome --disable-web-security
For more information about the last item, you can read this post.
It seems that your issue is about local development only.
Create react app solves precisely this by supporting the dev server to serve as a proxy to your API endpoint.
Just add the API domain in the proxy
key in package.json. More on this here
For production you should either host them both under the same domain (using a reverse proxy to route static content vs api request based on the URL path), or find a permanent cors friendly solution on your backend.
Cors is a browser feature and cannot be disabled. Though, when not using the POST method you can get around the preflight but you still can't access the response body without the proper headers set