Search code examples
angularcorsxmlhttprequesthttp-headers

POST request blocked by CORS policy from local Angular application but works fine in Postman and Thunder Client


I'm developing a web app that requests a list of jobs from an api on a remote server, in the form of json, so I can insert them in a mat-table.

the company sent me a link to the list of API's that I need, along with a template that I can try requests with it. For clarification, it looks like this.

the POST request works like a charm on the template, with Postman and also Thunder Client (on VSCode).

  • these are the response headers:
 access-control-allow-credentials: * 
 access-control-allow-headers: content-type,server,strict-transport-security,x-powered-by,date 
 access-control-allow-methods: GET,HEAD,POST,PUT,DELETE,CONNECT,OPTIONS,TRACE,PATCH 
 access-control-allow-origin: * 
 access-control-expose-headers: * 
 content-type: application/json; charset=utf-8 
 date: Mon,04 Jul 2022 14:39:42 GMT 
 server: Microsoft-IIS/10.0 
 strict-transport-security: max-age=2592000 
 x-content-type-options: nosniff 
 x-powered-by: ASP.NET

However, it raises an error when performing the request from my Angular app, this is the error on Brave Browser Console:

Access to XMLHttpRequest at '(***API URL***)' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

This is the error on Mozilla Firefox Console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://blmbwebapi.weker.fr/api/jobs/listJobs. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 405.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://blmbwebapi.weker.fr/api/jobs/listJobs. (Reason: CORS request did not succeed). Status code: (null).

my code looks like this:

*list-jobs.service.ts: (Snippet)

export class ListJobsService {

  public baseUrl = "/* API URL */";

  constructor(private httpClient: HttpClient) { }

  public getJobs(): Observable<any> { 

    let body = {"pageIndex": 0,
                "pageSize": 10,
                "filters": [ {"filterName": "csvFile", 
                              "filterValue": "flash-sales-export_20170217_080032.csv", 
                              "filterValues": [ "string" ] } ],
                "sortInfos": [ {"sortColumn": "string",
                                "sortOrdor": 0 } ] };


    let options = { headers: new HttpHeaders().set('Content-Type', 'application/json') };
    return this.httpClient.post(this.baseUrl,body, options);
   }

jobs.component.ts:(Snippet)

ngOnInit(): void {

    this.listJobsService.getJobs().subscribe(data => {
      this.jobs = data;
      console.log(data);});
    
  }

If any further information is need, please tell me!

Thank you so much.


Solution

  • Problem Solved

    I worked around it with Angular CLI Proxy, and created a proxy.conf.json file in my root folder. I needed to fool my browser by by pretending to have the API on the same origin. there is no Bearer token or API Key needed for it.

    then I started my app with:

    ng serve --proxy-config proxy.conf.json

    my proxy.conf.json file contains this:

    {
        "/api": {
            "target": "(THE REAL API URL)",
            "secure": true,
            "changeOrigin": true,
            "pathRewrite": {
                "^/api": ""
            }
        }
    }
    
    • /api property of the object specifies the route for the proxy and the nested object specifies the configuration. So I changed my api url in the service method to http://localhost:4200/api.
    • pathRewrite property allowed me modify how the application interacts with the target.

    It became:

    export class ListJobsService {
    
      public baseUrl = "http://localhost:4200/api";
    
      constructor(private httpClient: HttpClient) { }
    
      public getJobs(): Observable<any> { 
    
        let body = {"pageIndex": 0,
                    "pageSize": 10,
                    "filters": [ {"filterName": "csvFile", 
                                  "filterValue": "flash-sales-export_20170217_080032.csv", 
                                  "filterValues": [ "string" ] } ],
                    "sortInfos": [ {"sortColumn": "string",
                                    "sortOrdor": 0 } ] };
    
    
        let options = { headers: new HttpHeaders().set('Content-Type', 'application/json') };
        return this.httpClient.post(this.baseUrl,body, options);
       }