node.js - 如何将我的工作 curl 命令映射到 grpc-web 调用
问题描述
我正在尝试获取grpc-web的工作实例。我有一个看起来像这样的后端服务。
var grpc = require('grpc');
var messages = require('./example_pb');
var service = require('./example_grpc_pb');
function exampleOne(call) {
var response = new messages.ExampleOneRequest();
call.write(response);
call.end();
}
function main() {
var server = new grpc.Server();
server.addService(
services.MyExampleService,
{
example : exampleOne
}
);
server.bind('0.0.0.0:8050', grpc.ServerCredentials.createInsecure());
server.start();
}
main();
我已经用服务器端的“客户端”对此进行了测试,所以现在我正在尝试连接实际的基于 Web 浏览器的客户端。首先我设置了代理,这显然是必要的?我决定使用基于GoLang 的grpcwebproxy,根据 grpc-web 文档,这似乎是一个可以接受的选择。
>> grpcwebproxy --backend_addr=localhost:8050 \
--server_tls_cert_file=/usr2/certs/server/localhost.localdomain.crt \
--server_tls_key_file=/usr2/certs/server/localhost.localdomain.key
输出看起来像这样
INFO[0000] dialing to target with scheme: "" system=system
INFO[0000] ccResolverWrapper: sending new addresses to cc: [{localhost:8050 0 <nil>}] system=system
INFO[0000] listening for http on: [::]:8080
INFO[0000] listening for http_tls on: [::]:8443
INFO[0000] pickfirstBalancer: HandleSubConnStateChange: 0xc4201638a0, CONNECTING system=system
INFO[0000] pickfirstBalancer: HandleSubConnStateChange: 0xc4201638a0, READY system=system
我无法让网络浏览器实现工作,只是得到一些通用/CORS 相关的 500 错误。
我回到我的服务器端并决定卷曲代理。我当前的 curl 版本似乎不支持 http2,所以我改用了一个名为 h2c 的工具。
长话短说,我尝试 ping tls 端口 8443 并获得以下信息(最有希望的)。
>> ./h2c_linux_amd64 get https://localhost:8443/service.path/ExampleOne
invalid gRPC request method
我试试这个
>> ./h2c_linux_amd64 get http://localhost:8443/service.path/ExampleOne
http connections not supported.
我试试这个
>> ./h2c_linux_amd64 get http://localhost:8080/service.path/ExampleOne
http connections not supported.
我试试这个
>> ./h2c_linux_amd64 get https://localhost:8080/service.path/ExampleOne
Failed to connect to localhost:8080: tls: oversized record received with length 20527
我不希望立即出现“这是您的解决方案”类型的答案,因为我遗漏了很多内容,但是有人对在哪里运行有任何建议吗?
我得到的错误
"invalid gRPC request method"
如果通用的话,似乎是最有希望的。
编辑 :
似乎已经接近了一点,至少调试了服务器端。回到使用卷曲。这是我的命令
curl 'https://localhost:8443/service.path/ExampleOne' \
-H 'content-type: application/grpc-web+proto' \
-H 'x-grpc-web: 1' \
-H 'authority: localhost:8443' \
--data-binary $'\x00\x00\x00\x00\x04\n\x02yo' \
--insecure
使用此命令,我能够通过 grpcwebproxy 访问我的服务,然后返回另一端。用二进制字符串提供 curl 似乎可以解决问题。我这么说是因为
curl 'https://localhost:8443/service.path/ExampleOne' \
-H 'content-type: application/grpc-web+proto' \
-H 'x-grpc-web: 1' \
-H 'authority: localhost:8443' \
--insecure
导致错误消息
gRPC requires HTTP/2
现在我需要将上面的 curl 命令映射到一个有效的 grpc-web 请求中。
编辑 2:
我现在正处于我认为我需要证书的地步。浏览器中的代码正在访问我的 grpcwebproxy,但我看到了错误消息
2018/10/17 12:21:56 http2: server: error reading preface from client 127.0.0.1:45056: remote error: tls: unknown certificate authority
2018/10/17 12:21:56 http2: server: error reading preface from client 127.0.0.1:45058: remote error: tls: unknown certificate authority
2018/10/17 12:21:56 http2: server: error reading preface from client 127.0.0.1:45060: remote error: tls: unknown certificate authority
这发生在 grpcwebproxy 的输出中,所以我知道请求至少在那里。
我想我以前通过包含 --insecure 标签来解决这个问题......不知道如何在浏览器中复制它。
解决方案
您可以选择从我们的 Echo 示例开始,然后从那里进行调整。我刚刚尝试了我们的示例(使用 grpcwebproxy 的示例)并且有效。
$ git clone https://github.com/grpc/grpc-web
$ cd grpc-web
$ docker-compose build prereqs common node-server grpcwebproxy binary-client
$ docker-compose up -d node-server grpcwebproxy binary-client
浏览器:localhost:8081/echotest.html
从浏览器中,如果我“复制为 cURL”,我得到了
curl 'http://localhost:8080/grpc.gateway.testing.EchoService/Echo' -H 'Pragma: no-cache' -H 'X-User-Agent: grpc-web-javascript/0.1' -H 'Origin: http://localhost:8081' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9' -H 'custom-header-1: value1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' -H 'Content-Type: application/grpc-web+proto' -H 'Accept: */*' -H 'X-Grpc-Web: 1' -H 'Cache-Control: no-cache' -H 'Referer: http://localhost:8081/echotest.html' -H 'Connection: keep-alive' --data-binary $'\x00\x00\x00\x00\x05\n\x03abc' --compressed
推荐阅读
- .htaccess - 使用 .htaccess 将所有子域和子目录重定向到索引页面
- javascript - 如何在 JavaScript 中映射嵌套数组,然后检查嵌套数组的属性之一是否没有值?
- git - 为什么 git 不能在获取或远程分支上记录特定范围的提交?
- python - 使用 ItemLoader 设置布尔值
- python - 乘以不同维度的数据框 Pandas:列数相同,但行数不同
- flutter - 在服务器发送请求后运行函数的最佳方式是什么?
- javascript - 在反应中显示来自api的数据
- reactjs - 组件道具 ReactJS 的 PropType
- r - 使所有嵌套列表等于 R 中最小(最小长度)列表的长度
- c# - EF Core 不必要地跟踪子对象