Fixing CORS errors with Angular CLI proxy
Trying to access an API endpoint while building on localhost can be traumatizing, especially when this error “No ‘Access-Control-Allow-Origin’ header is present on the requested resource” comes up. Don’t worry it wasn’t your fault, the error is due to the same-origin policy that is implemented by most browsers.
The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. — source
The reason you are getting the error is because you’re making a request to a different origin from the one you’re currently on. Take for example, your application is running on http://localhost:4200
when you’re trying to access the resource from https://api.spotify.com/v1
. localhost
and api.spotify.com
are two different origins which are also running on different protocols http
and https
respectively, this is a cross-origin request, and it’s enough reason for your browser to fume about you flaunting its rules. If the server had specified your origin in its header, you also won’t be facing this challenge.
What can we do about it?
Using a Proxy
You may not always have access to the code running on the server. In this case, what you can do is to set up a proxy for your angular application. The Proxy basically attempts to fool the browser, it does this by pretending to have the API on the same origin whereas underneath the hood it's accessing the resource from another origin. This way the browser would be able to believe the same-origin policy is being adhered to, thereby taking out the CORS error.
How do we achieve this, let’s get into it right away.
Step 1:
Create a proxy.conf.json file and copy the following code into it.
A few things to note here:
"/api”
property of the object specifies the route for the proxy and the nested object specifies the configuration. Hence in order to make requests, the url will behttp://yourhost/api
(for my project, that would behttp://localhost:4200/api
).“target”
property of the nested object specifies the API url you’re trying to reach, in this case spotify.com.“secure”
property is used to specify whether the target is being served over http or https. It is currently set to true because the spotify.com endpoint is being served over https.“changeOrigin”
property specifies that the target is on another domain different from that which the app is currently running on. In this case, it is set totrue
because the application is running onlocalhost
while the target is onspotify
. If they were both onlocalhost
then it would be false."pathRewrite"
property allows you modify how the application interacts with the target. Without the“pathRewrite”
property, every call to the proxy urlhttp://localhost:4200/api
will correspond tohttps://api.spotify.com/v1/api
. This wouldn’t be a problem if spotify has anapi
endpoint, but since in reality they don’t provide such endpoint, this would lead to an error. Hence, setting the"pathRewrite"
nested object with“^/api”: “”
helps remove the unwanted “api” at the end of the url. This in turn ensures that callinghttp://localhost:4200/api
will correspond tohttps://api.spotify.com/v1
.
Step 2:
Set your application to work with the proxy using either of two methods:
- By running
ng serve --proxy-config proxy.conf.json
Ensure that theproxy.conf.json
file is created at your base directory. - The other option is to modify the
angular.json
file and add the following lines of code to thearchitect
configuration object.
A few things to note:
The serve property is already preconfigured in your angular.json file, the only addition you need to add is on line 5.
Once this has been added, run ng serve
to start your application.
On production environment
I found it easier to create the proxy server on Nginx. Unfortunately the configuration of the Nginx server is beyond the scope of this article, I’d write about it on another post.
Other approach
If you have access to the server running the endpoint, you can simply add Access-Control-Allow-Origin: *
to your header to allow all origins or you can add Access-Control-Allow-Origin: http://localhost:4200
to allow only requests from the localhost.
Further reading
Cross origin request sharing (CORS)
Angular — Proxying to a backend server
Please drop your comments, questions or feedback in the comment section below and I’ll reply as soon as possible.
Also, if you made it this far please keep going and drop a clap or two. That would really make my day. :).