I am trying to get a working instance of grpc-web. I've got a backend service that looks like this.
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();
I've tested this with a server side 'client', so now I am attempting to hook up the actual web browser based client. First I set up the proxy, which apparently is necesary? I decided to go with the GoLang based grpcwebproxy, which seems like an acceptable choice according to the grpc-web documentation.
>> 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
Output looks like this
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
I am unable to get the web-browser implentation working, just getting some generic/CORS related 500 errors.
I went back to my server side and decided to curl the proxy. It seems that http2 is not supported with my current version of curl, so I instead use a tool called h2c.
Long story short, I try pinging the tls port 8443 and get the following (most promising).
>> ./h2c_linux_amd64 get https://localhost:8443/service.path/ExampleOne
invalid gRPC request method
I try this
>> ./h2c_linux_amd64 get http://localhost:8443/service.path/ExampleOne
http connections not supported.
I try this
>> ./h2c_linux_amd64 get http://localhost:8080/service.path/ExampleOne
http connections not supported.
I try this
>> ./h2c_linux_amd64 get https://localhost:8080/service.path/ExampleOne
Failed to connect to localhost:8080: tls: oversized record received with length 20527
I don't expect an instant "this is your solution" type answer, since there's a lot I left out, but does anyone have any suggestions on where to run with this?
The error I got
"invalid gRPC request method"
seems the most promising, if generic.
EDIT :
Seem to have gotten a bit closer, at least debugging the server side. Went back to using curl. This was my command
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
With this command, I was able to make it through the grpcwebproxy, to my service, and back to the other side. Something about supplying curl with a binary string seems to do the trick. I say this because
curl 'https://localhost:8443/service.path/ExampleOne' \
-H 'content-type: application/grpc-web+proto' \
-H 'x-grpc-web: 1' \
-H 'authority: localhost:8443' \
--insecure
results in an error message of
gRPC requires HTTP/2
Now I need to map the above curl command into a valid grpc-web request.
EDIT 2 :
I am now at the point where I think I require a cert. The code from the browser is hitting my grpcwebproxy, but I am seeing the error message
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
This occurs in the output of grpcwebproxy, so I know the request is at least making it there.
I'm thinking I got around this previously with curl by including the --insecure tag... not sure how to replicate this in the browser.