21

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?

2
  • What’s the HTTP status code of the response? Commented Nov 27, 2018 at 3:45
  • @Arup Sarkar, if applicable kindly mark the correct answer Commented Oct 14, 2019 at 7:21

7 Answers 7

8

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

Sign up to request clarification or add additional context in comments.

Comments

8

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!

Comments

6

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.

3 Comments

Thx for the explanation. That's what I did but I still have an issue with Angular 9 with Express.js Access to XMLHttpRequest at 'localhost:7777/api/login' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
@DineshKumar I am not the original owner of this answer, I just edited it to have a clear code format, you should ask TiyebM. In any case, I suppose yes, but I did not try.
Hi, the target is set "localhost:3000`". Then in QA or PRODUCTION, how to set it? We just have one proxy file.
2

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.

1 Comment

For .net core, check this out: c-sharpcorner.com/article/…
2

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);

Comments

0

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)

Comments

0

At angular make a simple request

   SaveStarRating(data: FormData) {
var myheader =  this.persistanceService.get("token") ;

const endpoint = AppConstants.baseAPIurl + "v1/xyz/ProductFull/SaveStarRating";
  var httpOptions = {
    headers: new HttpHeaders(
      { 'token': myheader 
     }  )
  };
return this._http
  .post(endpoint, data, httpOptions);

}

At API end make the following changes

 public class CorsHandler: DelegatingHandler {

  private
  const string Origin = "Origin";
  private
  const string AccessControlRequestMethod = "Access-Control-Request-Method";
  private
  const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
  private
  const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
  private
  const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
  private
  const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
  protected override Task < HttpResponseMessage > SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
    bool isCorsRequest = request.Headers.Contains(Origin);
    bool isPreflightRequest = request.Method == HttpMethod.Options;

    if (isCorsRequest) {
      if (isPreflightRequest) {
        var response = new HttpResponseMessage(HttpStatusCode.OK);
        //  response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());

        string accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
        if (accessControlRequestMethod != null) {
          response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
        }

        string requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
        if (!string.IsNullOrEmpty(requestedHeaders)) {
          response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
        }

        var tcs = new TaskCompletionSource < HttpResponseMessage > ();
        tcs.SetResult(response);
        return tcs.Task;
      }

      return base.SendAsync(request, cancellationToken).ContinueWith(t => {
        HttpResponseMessage resp = t.Result;
        //  resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
        return resp;
      });

      var sd = base.SendAsync(request, cancellationToken).ContinueWith(t => {
        HttpResponseMessage resp = t.Result;
        //  resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
        return resp;
      });

      return sd;

    }
    return base.SendAsync(request, cancellationToken);
  }

}

In Web Config Add

<httpProtocol>
<customHeaders>
    <add name="Access-Control-Expose-Headers" value="token, tokenexpiry, role" />
    <add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>

Add another in web.config

<system.web> <httpRuntime maxRequestLength ="2097151"/>

In your API project add references Microsoft.AspNetCore.Cors.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Cors.dll

In your controller your can add

 [EnableCors("AllowAllHeaders")]
 [AuthorizationRequired]

 [AttributeRouting.RoutePrefix("v1/CarParts/ProductFull")]
 public class ProductFullController: ApiController {

In your API action method in you controller

[EnableCors("AllowAll")]
[POST("SaveStarRating")]
public HttpResponseMessage SaveStarRating()

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.