grpc-web client in reactjs

Created on 1 Dec 2018  路  7Comments  路  Source: grpc/grpc-web

Hi,

my grpc client is react js, server grpc in csharp
Docker on windows 10 with envoy proxy running.
image

I run this command and generated my js files (on linux ubuntu 16):

sudo protoc -I=. proto.proto --js_out=import_style=commonjs:generated --plugin=protoc-gen-grpc-web=/home/grpc-web-master/javascript/net/grpc/web/protoc-gen-grpc-web --grpc-web_out=import_style=commonjs,mode=grpcwebtext:generated

Now in the client side:

import { ProtocolServiceClient } from '../output/proto_grpc_web_pb'
import { UserInfo } from "../output/proto_pb";

const grpcHost = "http://127.0.0.1:8085";
const client = new ServiceClient(grpcHost, {}, {});

const request = new UserInfo();
request.setName('a');
const metadata = {};
client.connect(request, metadata ,function(err, response) {
  if (err) {
    console.log(err.code);
    console.log(err.message);
  } else {
    console.log(response);
  }
});

Tried to add metaadata to the request with so many types of metadata, nothing worked

metadata = {'content-type': 'application/grpc-web-text'};
metadata = {'content-type': 'application/grpc'};
metadata = {'content-type': 'application/grpc-web'};
metadata = {'content-type': 'application/grpc-web+proto'};
metadata = {'content-type': 'application/grpc-web+json'};

And the result is:
POST http://127.0.0.1:8085/ProtocolProtos.ProtocolService/Connect 503 (Service Unavailable)
And receive back a gRPC error code 14 => upstream connect error or disconnect/reset before headers

What am I missing?
Please help me, I'm a struggling with this for a very long time.

Here is my envoy.yaml file:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9903
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 8085
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: protocol_service
                  max_grpc_timeout: 10s
              cors:
                allow_origin:
                - "*"
                allow_methods: GET, PUT, DELETE, POST, OPTIONS
                allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                max_age: "1728000"
                expose_headers: custom-header-1,grpc-status,grpc-message
                enabled: true
          http_filters:
          - name: envoy.grpc_web
          - name: envoy.cors
          - name: envoy.router
  clusters:
  - name: protocol_service
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    # dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    http2_protocol_options: {}
    hosts:
      - socket_address:
          address: 0.0.0.0
          port_value: 9090

And here is my Dockerfile:

FROM envoyproxy/envoy:latest
COPY envoy.yaml /etc/envoy/envoy.yaml
CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml

To run the image I did:

docker build -f envoyDockerfile -t envoy:v14 .
docker run -d --name envoyv148085 -p 9903:9903 -p 8085:8085 envoy:v14

Any help figuring out why it doesn't work will be highly appreciated.

Most helpful comment

Thanks for your help everyone! Indeed it works with host.docker.internal. Now I understand my mistake.
My code is hosted here.

All 7 comments

Hello @AnaitBI
I have the same error running on Windows 10 while running the helloworld example. Does grpc-web example work out for you?

Here's the command with curl I'm using (my envoy server listens on 8080):

curl -skv 'http://localhost:8080/helloworld.Greeter/SayHello' -H '
content-type: application/grpc-web+proto' -H 'x-grpc-web: 1' -H 'accept: application/grpc-web-text' --data-binary 'AAAAAAA='

Which outputs:

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /helloworld.Greeter/SayHello HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.55.1
> content-type: application/grpc-web+proto
> x-grpc-web: 1
> accept: application/grpc-web-text
> Content-Length: 8
>
* upload completely sent off: 8 out of 8 bytes
< HTTP/1.1 200 OK
< content-type: application/grpc-web-text+proto
< grpc-status: 14
< grpc-message: upstream connect error or disconnect/reset before headers
< date: Sat, 01 Dec 2018 21:53:35 GMT
< server: envoy
< content-length: 0
<
* Connection #0 to host localhost left intact

Same result as you have.

Running the echo example with docker-compose runs fine though.

@jdebarochez
Yes, also did not work

I don't fully understand how your servers are setup, but if you are using docker for windows to run the envoy container, and your gRPC server is listening on localhost in your windows machine, then envoy cannot talk to it.

In the clusters entry of envoy.yaml, instead of address: 0.0.0.0 try address: host.docker.internal

@alce
All are on one windows machine the docker, the image and the gRPC.
What address exactly should be changed to' host.docker.internal', what does it mean?

@alce
All are on one windows machine the docker, the image and the gRPC.
What address exactly should be changed to' host.docker.internal', what does it mean?

In the clusters entry of envoy.yaml
instead of address: 0.0.0.0
try address: host.docker.internal

@longfellowone @AnaitBI

Changing the address as I explain above is a potential potential fix for connection failures only when:

  • You are using docker for Windows (or Mac)
  • You only use docker to run the envoy proxy (but not the gRPC backend)
  • You are running the gRPC backend directly on your development machine.

What host.docker.internal does is explained here for Windows users and here for Mac users. In a nutshell, this change allows your envoy container to connect to an gRPC server running directly on your development machine (as opposed to the virtual machine docker uses to run your containers).

Thanks for your help everyone! Indeed it works with host.docker.internal. Now I understand my mistake.
My code is hosted here.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

oferb picture oferb  路  5Comments

peteringram0 picture peteringram0  路  5Comments

developerlaoz picture developerlaoz  路  3Comments

smnbbrv picture smnbbrv  路  4Comments

graup picture graup  路  4Comments