无法从 Angular 客户端调用 gRPC 服务

Unable to call gRPC service from Angular client

我正在尝试从 Angular 应用程序调用 gRPC 服务。

如果我在本地托管服务器并从 Anuglar 应用程序调用它,那么它就可以工作。

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

但是,当我尝试调用托管在远程服务器上的 gRPC 服务时,它抛出“没有 headers 的情况下关闭响应”错误。

更改代码:

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

如果我尝试使用 NodeJS 客户端调用托管在服务器上的相同服务,那么它也能正常工作。

NodeJS 代码:

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

Angular 应用程序无法调用服务器上托管的 gRPC 服务的原因可能是什么?

Chrome 开发工具日志:

这很可能是由常见问题引起的 CORS Browser restrictions, and not exactly by angular. This question 包含关于 CORS 的重要指导。

从 Node 应用程序(或邮递员)调用 HTTP 服务不会强制执行 CORS,而从市场标准浏览器调用它肯定会。

我知道它比我的下一个简化评论要多得多,但这应该给你一个起点(更深入的探讨在我上面分享的链接中)

对于浏览器执行XMLHttpRequest's从一个网站到其他域(或同一域的其他端口):

  1. 浏览器将在每次向其他域发出真实请求之前发送一个 OPTIONS HTTP 请求,并且仅当 OPTIONS 响应 headers 授权时才允许实际请求。
  2. “其他”网站必须配置为使用特定 Headers(Access-Control-Allow-OriginAccess-Control-Request-* ...)回复 OPTIONS 请求。

==> 如果其他服务器未回复 OPTIONS 请求或未在 OPTIONS 响应中提供适当的 headers,您会得到一系列不同的错误,并且“Response closed without headers" 就是其中之一。

我认为您的 gRPC Web 应用程序没有配置正确的 CORS 来授权来自您托管 angular 应用程序的网站的通信(即使它是本地主机,您仍然需要配置它) .

This article 有关于如何在 .netcore 应用程序上配置 CORS 的实用指南

最后,This github issue / responses 包含一些关于一些人在使用 gRPC 时遇到的类似错误的更多信息,您可能遇到过相同的错误。如果您已经配置了 CORS 规则。

我建议不要直接从您的浏览器客户端调用您的后端(如果您不想这样做,请告诉我)并改用反向代理。有很多工具可以做到这一点:

事实上,gRPC 的 Github 存储库中的示例使用了 envoy(grpc-io 邮件列表中的 check here) and one of the mail 提到不建议直接将后端与 gRPC 网络前端联系。