Search code examples
angular.net-coregrpcgrpc-web

Unable to call gRPC service from Angular client


I am trying to call a gRPC service from Angular application.

If I host the server locally and call it from Anuglar application then it works.

    const client = new HelloWorldServiceClient("http://localhost:5001");
          
    const request = new SayHelloMessage();
    request.setName("User");
    
    client.sayHelloWorld(request, (err: any, response: any) => {
            
    if (err) {
         console.log(err);
         this.response = err;
         return;
    }
    this.response = response.getMessage();
  });

However, when I try to call a gRPC service hosted on a remote server it throws "Response closed without headers" error.

Changed code:

const client = new HelloWorldServiceClient("http://server_name:5001");

If I try to call the same service hosted on a server using NodeJS client then it works too.

NodeJS Code:

var url = "server_name_with_out_http:5001"; // e.g. server_name:5001 and not http://server_name:5001

const client = new HelloWorldServiceClient( 
    url,
    grpc.credentials.createInsecure()
);

var req = { name: "User" };

client.sayHelloWorld(req, (error, reply) => {
    if (!error) {
        console.log(reply.message);
    } else {
        console.log(error);
    }
});

What could be the reason why Angular application is not able to call gRPC service hosted on the server?

Chrome dev tool logs:

enter image description here

enter image description here

enter image description here


Solution

  • This is most likely caused by the common CORS Browser restrictions, and not exactly by angular. This question contains great guidance on CORS.

    Calling HTTP services from a Node app (or from postman) will not enforce CORS, while calling it from a market standard browser certainly would.

    I know there is far more to it than my next simplified comments but this should give you a starting point (a deeper dive is in the links I shared above)

    For browsers to execute XMLHttpRequest's from one website to other domains (or other ports of the same domain):

    1. the browser will send an OPTIONS HTTP request before every real request to the other domain and only allow the actual request when the OPTIONS response headers authorize it.
    2. the "other" website must be configure to reply to OPTIONS requests with specific Headers (Access-Control-Allow-Origin, Access-Control-Request-* ...).

    ==> If the other server does not reply to OPTIONS requests or does not provide the appropriate headers in the OPTIONS response, you can get a range of different errors, and "Response closed without headers" is one of them.

    I believe your gRPC web application is not configured with the proper CORS to authorize communications from the website where you are hosting your angular application (even if it is localhost, you would still need to configure it).

    This article has practical guidance on how to configure CORS on .netcore applications

    and finally, This github issue / responses contains some more info about a similar error some people faced with gRPC, you might have stepped into the same one. If you have already configured your CORS rules.