TL;DR: CORS issues can significantly hinder development by blocking legitimate API requests. Angular Dev Proxy is a powerful tool for bypassing CORS during development. Learn the importance of addressing CORS and the step-by-step guide to setting up Angular Dev Proxy. This article includes creating a new Angular app, setting up a data service, and updating components for seamless data fetching.
Browsers use a Cross-origin resource sharing (CORS) mechanism to prevent harmful websites from making requests to other websites without permission. However, this can be an obstacle for developers, especially when they block legitimate API requests during development. I’m sure almost all developers have had a CORS issue at least once since StackOverflow has over 100K questions related to CORS.
This article will discuss the importance of handling CORS issues and how to set up and use Angular Dev Proxy to avoid them in five easy steps.
Cross-Origin Resource Sharing (CORS) is a set of web security tools devised for how a webpage demands resources from another domain. These are with additional HTTP headers such as:
When a web app tries to request a resource on a different origin, the browser and server communicate using these headers to determine if the request is allowed.
For example, consider the above CORS error message. In this case, the Angular app hosted at http://localhost:4200 attempts to access http://localhost:3000/api/data, of which status has been blocked by the browser because there was no Access-Control-Allow-Origin header in its response.
But why does it need addressing if it is a security measure that the browsers use?
While stopping malicious websites from sending unauthorized requests to other domains, CORS may also prevent legitimate requests necessary to properly operate web apps. Thus, it is essential to address CORS problems to allow safe and effective legitimate cross-origin requests.
Here are some of the common issues developers face due to CORS:
The Angular Dev Proxy allows developers to bypass CORS issues during development by configuring a proxy server that intercepts API requests and forwards them to the target server.
Here are the steps you need to follow to create an Angular Dev Proxy:
Note: You can skip this step if you already have an Angular app. However, I will be using standalone components of Angular 17 for this implementation.
To create a new Angular app, use the following command:
ng new angular-17-dev-proxy cd angular-17-dev-proxy
Create a new service named data.service.ts and update it with the following code to fetch data from the server.
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataService { constructor(private http: HttpClient) {} getData(): Observable<any> { return this.http.get('/api/data'); // The proxy will forward this to http://localhost:4000/api/data } }
Then, update app.component.ts and app.component.html files to display fetched data. Since we created a standalone app, there won’t be an app.module.ts file, and app.component.ts will have the standalone: true configuration.
app.component.ts
import { Component } from '@angular/core'; import { DataService } from './data.service'; import { CommonModule } from '@angular/common'; @Component({ selector: 'app-root', standalone: true, templateUrl: './app.component.html', imports: [CommonModule], styleUrl: './app.component.scss' }) export class AppComponent { title = 'angular-17-dev-proxy'; data: any; constructor(private dataService: DataService) {} ngOnInit(): void { this.dataService.getData().subscribe( data => { console.log(data); this.data = data; }, (error) => { console.error('Error fetching data:', error); } ); } }
app.component.html
<div *ngIf="data">
<h2>Data from API</h2>
<pre>{{ data | json }}</pre> </div> <div *ngIf="!data">
<p>Loading data...</p> </div>
You may get a run time error like this when you run the above code example.
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient() ] };
Create a new file named proxy.conf.json in the root of your Angular project. This proxy configuration file allows you to define how specific requests should be proxied to a different server.
{ "/api": { "target": "http://localhost:3000", "secure": false, "changeOrigin": true, "logLevel": "debug" } }
After creating the proxy configuration file, you need to update the package.json file to use this proxy configuration.
"scripts": { "ng": "ng", "start": "ng serve --proxy-config proxy.conf.json", "build": "ng build", "watch": "ng build --watch --configuration development", "test": "ng test" }
Use the npm start command to run the app. Since we addressed the CORS issue, you will see the data fetched from the server in the browser tab.
If you open the DevTool Network tab, you will see that the request was made to localhost:4200/api/data, and the proxy has routed it to the server at localhost:3000.
Node.js and Angular apps used in this example are available at these GitHub repos:
Here are some advanced proxy configurations you can use to handle more complex development scenarios:
{ "/api": { "target": "http://localhost:3000", "secure": false, "changeOrigin": true, "logLevel": "debug", "pathRewrite": { "^/api": "" } }, "/auth": { "target": "http://localhost:4000", "secure": false, "changeOrigin": true, "logLevel": "debug", "pathRewrite": { "^/auth": "" } } }
{ "/api/v1/*": { "target": "https://api.example.com/v1", "secure": false, "changeOrigin": true, "logLevel": "debug", "pathRewrite": { "^/api/v1": "" } } }
{ "/api": { "target": "http://localhost:3000", "secure": false, "changeOrigin": true, "logLevel": "debug", "headers": { "X-Custom-Header": "value" } } }
{ "/api": { "target": "https://api1.example.com", "router": { "host2.example.com": "https://api2.example.com" }, "secure": false, "changeOrigin": true, "logLevel": "debug" } }
Here are some common issues and solutions you might need when working with Angular Dev Proxies.
Cause: This typically indicates an issue with the backend server or the proxy configuration.
Solution:
{ "/api": { "target": "http://localhost:3000", "pathRewrite": { "^/api": "" } } }
Cause: The proxy path or target URL may be incorrect.
Solution:
Cause: The request may not be reaching the server, or the server may not be responding.
Solution:
In this article, we demonstrated how important it is to handle CORS issues and how easy Angular Dev Proxy makes it. With all its other capabilities, Angular Dev Proxy can act as a reverse proxy between your multiple backend services, rewrite complex URL paths, or add custom headers, ensuring robust and secure communication of Angular app frontend with backend APIs.
The Syncfusion Angular UI components library is the only suite that you will ever need to build an application since it contains over 85 high-performance, lightweight, modular, and responsive UI components in a single package.
For existing customers, the newest version of Essential Studio® is available for download from the License and Downloads page. If you are not a Syncfusion customer, try our 30-day free trial to check out its features.
If you have questions, you can contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!