17
votes

I have developed an angular 7 app with express backend. Express running on localhost:3000 and angular client is running on localhost:4200.

In the server.js I have (not the entire code)

const app = express();
// Enable CORS
app.use(cors());
// Get our API routes
const api = require('./api');
// Set our api routes
app.use('/api', api);
app.use(express.static(__dirname + '/dist/sfdc-event'));

In the api.js file, I have router.get(‘/oauth2/login’) which redirects to https://example.com which sends an access token and authenticates the user (OAuth2 authentication).

When I am calling the url http://localhost:3000/api/oauth2/login everything is working fine, but when I am trying to do the same from angular component.ts -> service.ts I am getting the following error.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource Reason: CORS header ‘Access-Control-Allow-Origin’ missing

Angular app flow as follows login.component.ts which has a button calling a service api.service.ts which executes a http get.

login.component.ts

sfdcLogin(): void {
  console.log('DEBUG: LoginComponent: ', 'Login button clicked..');
 this.apiService.login().subscribe( data => { console.log( data ); });
}

api.service.ts

login() {
  console.log('DEBUG: APiService login(): ', 'login() function.');
  const URL = 'oauth2/login';
  console.log('DEBUG: ApiService login URL : ', `${environment.baseUrl}/${URL}`.toString());
  return this.http.get(`${environment.baseUrl}/${URL}`)
    .pipe( map( res => res ));
}

Can someone help me get past the error? I have a) CORS b) serving static files from server.js as

app.use(express.static(__dirname + '/dist/sfdc-event'));

c) dynamic environment variable. What else I am missing?

8
What’s the HTTP status code of the response?sideshowbarker
@Arup Sarkar, if applicable kindly mark the correct answerAaron Matthews

8 Answers

7
votes

For Angular 7 you must do other implementation. From angular documentation you must create a proxy.js file:

https://angular.io/guide/build#using-corporate-proxy

Edit the path for your own backend server.

proxy.js:

var HttpsProxyAgent = require('https-proxy-agent');
var proxyConfig = [{
  context: '/api',
  target: 'http://your-remote-server.com:3000',
  secure: false
}];

function setupForCorporateProxy(proxyConfig) {
  var proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
  if (proxyServer) {
    var agent = new HttpsProxyAgent(proxyServer);
    console.log('Using corporate proxy server: ' + proxyServer);
    proxyConfig.forEach(function(entry) {
      entry.agent = agent;
    });
  }
  return proxyConfig;
}

module.exports = setupForCorporateProxy(proxyConfig);

Later add this to your package.json

"start": "ng serve --proxy-config proxy.js"

And call this with:

npm start

And in your app.js just simply add:

const cors = require("cors");
app.use(cors());

I had same problem and that solved my issue. I hope it helps!

5
votes

If this is just for development I recommend using proxy that comes with angular-cli. Create a file called proxy.json

and

{
  "/api/oauth2/login": {
    "target": "http://localhost:3000/api/oauth2/login",
    "secure": false
  }
}

and the call ng serve --proxy-config proxy.json. If you expect this to be still a problem in production then we have to have a bigger conversation.

Full documentation: https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md

Also what is CORS exacly: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

4
votes

To divert all calls for http://localhost:4200/api to a server running on http://localhost:3000/api, take the following steps.

  1. Create a file proxy.conf.json in the projects src/ folder, next to package.json.

  2. Add the following content to the new proxy file:

{
    "/api": {
        "target": "`http://localhost:3000`",
        "secure": false
    }
}
  1. In the CLI configuration file, angular.json, add the proxyConfig option to the serve target:
...
"architect": {
    "serve": {
        "builder": "@angular-devkit/build-angular:dev-server",
        "options": {
            "browserTarget": "your-application-name:build",
            "proxyConfig": "src/proxy.conf.json"
        },
    ...
    }
}
...
  1. To run the dev server with this proxy configuration, call ng serve.
2
votes

I have been working with Angular cli and .net Framework in server side.

To solve this problem, I just ennable CORS interaction in server side using the following steps:

  1. Install-Package Microsoft.AspNet.WebApi.Cors -Version 5.2.6

    And then, into WebApiConfig class:

  2. Add using System.Web.Http.Cors;

  3. Inside Register(HttpConfiguration config) method:

var cors = new EnableCorsAttribute("http://localhost:4200", "*", "*");

config.EnableCors(cors);

or

var cors = new EnableCorsAttribute("*", "*", "*"); //origin, headers, methods

config.EnableCors(cors);
1
votes

I changed the callback mechanism to get past the CORS issue, I am utilizing a OAuth flow for the user to get authenticated from https://example.com which was redirecting to https://example.com/auth/callback, I was initiating the request from http://localhost:4200 and then sending the callback url to the server http://localhost:3000 and I was getting the CORS error.

Now, I am redirecting it to the client http://localhost:4200 and got past the CORS problem. All other calls for GET, POST, DELETE, PATCH is from the http://localhost:3000 which is working fine.

Thank you all for your inputs.

0
votes

By default, Angular sets some request header parameters out of which one is, 'Content-Type' whose default value is 'application/json'. which when I set to 'application/x-www-form-urlencoded' resolved the error for me.

Instead of using post method like:

this.http.post<any>(requestDetails['url'],requestDetails['data'])

First set the request headers using the HttpHeaders Class of Angular like:

let reqHeaders = new HttpHeaders({
   'Content-Type':'application/x-www-form-urlencoded'
});
this.http.post<any>(requestDetails['url'],requestDetails['data'],{headers:reqHeaders})

refer: https://angular.io/guide/http#adding-and-updating-headers

In my case, 'Access-Control-Allow-Origin' is also set to * for the response headers on the server, to accept requests from any origin (in development case mostly it is: localhost: 4200)

-1
votes

I know this is already answered, but it might help someone who is searching for CORS issue. You can follow below 3 steps to solve this issue. 1. Create proxy.conf.json file and put it at root level of your app. 2. In package.json file, add proxy parameter in ngstart 3. In angular.json, add proxy file entry. 4. Change all your rest calls to something like /api/getData.

Complete step by step tutorial is given here. http://www.codeyourthought.com/angular/proxy-to-make-http-call-in-angular/

-4
votes

Since, your angular app is running on 4200 port and backend running on 3000 port, the origin of both the application is different.

To solve this problem, you can setup "nginx" in your machine.

This will make all your requests from angular and backend, go via "nginx" server. Thus, solving the problem of CORS.