grpc-web in react native fails to connect to envoy proxy server

34 Views Asked by At

I have a remote envoy proxy deployed in AWS with Elastic Beanstalk (for testing) with the configuration below:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 80 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: auto
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route:
                            cluster: grpc_cluster
                            timeout: 0s
                            max_stream_duration:
                              grpc_timeout_header_max: 0s
                      cors:
                        allow_origin_string_match:
                          - prefix: "*"
                        allow_methods: GET, PUT, DELETE, POST, OPTIONS
                        allow_headers: keep-alive,accept,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
                http_filters:
                  - name: envoy.filters.http.grpc_web
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
                  - name: envoy.filters.http.cors
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
    - name: grpc_cluster
      connect_timeout: 0.25s
      type: logical_dns
      http2_protocol_options: {}
      lb_policy: round_robin
      load_assignment:
        cluster_name: grpc_cluster
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: ${server_url}
                      port_value: ${server_port}

When I test connection to it using grpcurl or even a simple client via nodejs:

import { LightStreamerClient } from "../protos-dist/LightstreamerServiceClientPb";
import { Empty, ServerInfo } from "../protos-dist/lightstreamer_pb";
import { RpcError } from "grpc-web";

const XMLHttpRequest = require("xhr2");

const client = new LightStreamerClient("http://mytest.us-west-1.elasticbeanstalk.com");

globalThis.XMLHttpRequest = XMLHttpRequest;

function getServerInfo(): Promise<[RpcError, ServerInfo]> {
  return new Promise((res) => {
    client.getServerInfo(new Empty(), null, (_err, response) => {
      res([_err, response]);
    });
  });
}

async function main() {
  console.log("Testing envoy server...");
  const [err, response] = await getServerInfo();
  console.log({ err, response });
  console.log("Done.");
}

main();

it returns data as expected.

When I try to run this same grpc-web call from inside a simulated react native ios app, the call to the server fails with error: [RpcError: Http response at 400 or 500 level, http status code: 0]

Interestingly, when I run the same envoy proxy locally it works fine with all testing mechanisms. Wondering if it has something to do with CORS?

1

There are 1 best solutions below

0
jowparks On

We determined that iOS was blocking the insecure traffic on http, so we made a temporary exception in the Info.plist of our react native app and allowed insecure to our envoy.