grpc / grpc-web

gRPC for Web Clients
https://grpc.io
Apache License 2.0
8.65k stars 764 forks source link

grpc-web client in reactjs #402

Closed AnaitBI closed 5 years ago

AnaitBI commented 5 years ago

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.

jdebarochez commented 5 years ago

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.

AnaitBI commented 5 years ago

@jdebarochez Yes, also did not work

alce commented 5 years ago

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

AnaitBI commented 5 years ago

@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?

longfellowone commented 5 years ago

@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

alce commented 5 years ago

@longfellowone @AnaitBI

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

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).

jdebarochez commented 5 years ago

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