CORS - Cross-Origin Resource Sharing
Dec 31 2023 14:51
If you're working on your local development and try to consume api from internet, you face it some time
Access to fetch at 'http://localhost:4000/api' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
What it is, when & why it happens
We can call it's an error thrown by Browser
Happen when site https://abc.com try to request to resource from site https://api.xyz.com but it now allow to do that, then Browser will blocks the request
The reason you are not allowed because https://api.xyz.com only accept request coming from https:/xyz.com or from allow config list
"My house, only me and my family can get in"
Solutions
Resource owner
If you're resource owner, you need to config CORS to allow access from expected site for example in Spring boot CORS config I allow http://localhost:3000 to access in development env, and public domain https://pdminh.dev access in prod env
if (Arrays.stream(environment.getActiveProfiles()).anyMatch(p -> p.equals("dev"))) {
corsConfiguration.setAllowedOrigins(List.of("http://localhost:3000"));
} else {
corsConfiguration.setAllowedOrigins(List.of("https://pdminh.dev"));
}
Try to access localhost:4000/api from react localhost:3000 website, status is 200
Update my react app default port to 3001, get CORS error in consolog and status 403
Access to fetch at 'http://localhost:4000/api/weatherapi/v1/current.json?key=23ad9903220e4d1196243159231502&q=da+nang' from origin 'http://localhost:3001' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
You can also set allow origin to * to allow every where to access, the api of public service will set allow * for everyone to request
If you're not resource owner
As i said above, it's a error throw by Browser, you can access the api via postman or any application (not browser)
But the problem is you want to use the api in you react app, so you will need a proxy server to by pass browser block
Proxy server is just a web server that has function to forward request As a Java developer, I use Spring Zuul to build proxy server. Example available here Github
If you build your react app with nextjs, it already has function called rewrites which works the same
module.exports = () => {
const rewrites = () => {
return [
{
source: "/pdminhdevapi",
destination: "https://api.pdminh.dev",
},
];
};
return {
rewrites,
};
};
Conclusion
- CORS error you see on console is a feature of Browser
- CORS config in backend will strengthening web security
- We can bypass browser block by use proxy server, but you need to understand how it works first. I found some small problem but take time to resolve, Ex
Access to fetch at 'http://localhost:4000/api/weatherapi/v1/current.json?key=23ad9903220e4d1196243159231502&q=da+nang' from origin 'http://localhost:3000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:3000, \*', but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
It happened cause the proxy and the origin server both add Access-Control-Allow-Origin header I solved this problem by ignore header 'Access-Control-Allow-Origin' return from origin server
Delete comment
Confirm delete comment
Pham Duc Minh
Da Nang, Vietnam