Grpc-web: react native support?

Created on 6 Apr 2017  ·  24Comments  ·  Source: grpc/grpc-web

Will grpc-web officially support React Native?

Here's some more information about what that javascript execution environment looks like on various platforms.

Thanks!

Most helpful comment

Is there any update of trying grpc-web in React-Native?

All 24 comments

We will evolve the JS API for grpc-web, and Reactive Streams etc will certainly been taken into consideration.

I don't think we have any plan to support JS API for mobile platforms, but we should have the discussion.

Let's keep this issue open to track related future updates ... Thanks!

Thanks!

Just to clarify, this question is focused on support for Facebook's open source React Native framework, which allows you to write native apps using JavaScript. (This tool is unrelated to rx/reactive streams.)

Thanks for clarification. Does React Native offer any api specs too?

@wenbozhu I think this is the closest thing to a spec for React Native: https://facebook.github.io/react-native/docs/javascript-environment.html

Thanks for the links. We will evaluate if our client is portable to reactive native.

I had https://github.com/improbable-eng/grpc-web working with plain React so I dont see why React Native would pose any problem, just make a gRPC call with the js library like normal. Did you run into issues?

Any updates, did anyone get this working working with React-Native (RN)?

It uses polyfill.

grpc-web uses Google closure as the runtime ... and the new firestore web client has proven working on RN after we fixed one incompatible behavior (in RN) related to xhr.

https://github.com/google/closure-library/issues/858

I also attempted doing a "fix" in closure, which unfortunately broke <1% gmail clients (maybe due to plugins).

So, if you are familiar with RN, do give it a try and report back any issues.

Thanks.

I tried to get this running with React Native.
Snippet of my App.js
`var proto = require("./compiled.js");

export default class App extends React.Component {
constructor(props){
super(props);

    var service = new proto.proto.EchoServiceClient("http://localhost:8080");
    var unary_request = new proto.proto.EchoRequest();
    unary_request.setMessage("Test");
    service.echo(unary_request, {}, function(err, response){
        console.log("Unary echo response: " + response.getMessage());
    });
}
// render...`

At the end of the compiled.js I added the following to allow including the modal.
exports.proto = proto.grpc.gateway.testing;
I ran the backend server and nginx using docker.
Unfortunately, I am getting this error:
Unknown base64 encoding at char: :
c compiled.js:429:210

Did you compile Nginx from this repo or you use a standard Nginx?

I followed the instruction of the INSTALL.md and of the echo example. The nginx version is nginx/1.11.13.

I am also trying to get the grpc-web running on React-Native to avoid using code duplication for iOS and Android. I managed to generate the compiled.js file but everytime I want to "load" it I have an error. I tried both of the following options:
import './compiled.js';
var proto = require('./compiled.js');
But none of these work.
Did someone here managed to use the grpc-web with RN.
Thank you for your help.

Is there any update of trying grpc-web in React-Native?

Is there any update of trying grpc-web in React-Native?

Sorry, we don't have any local expertise to debug grpc-web on RN. We do know that goog-closure and its networking module (that grpc-web depends on) work fine on RN (e.g. in firestore/web).

So, if any of you likes to spend some serious time debugging the environment and working with us to get to the bottom of this, let me know. Thanks.

+1

any news?

+1 I'd like this too, I might be able to help support. What is the current state of this

For those waiting for this, if it helps: I was able to use grpc-web in a react-native expo app without any problems. Not sure how this relates to react-native without expo.

Code: https://github.com/tihu-nlp/tihu-native/blob/master/app/src/logic/api/speak.ts

Is there any work around for grpc-web with react-native cli app?

@shotor is right, you are able to connect from React Native (with and without Expo). Here is a Docker example where the server uses Go.

docker-compose.yml

version: "3.8"
services:
  envoy:
    build: ./envoy
    restart: always
    expose:
      - "2301"
    ports:
      - "2301:2301"
  server:
    build: ./server
    depends_on:
      - envoy
    ports:
      - "2302:2302"
    restart: always

The gRPC service (server) listens for connections on 2302 while the envoy proxy listens on 2301 and redirects to 2302, which is the gRPC service.

Dockerfile for envoy:

FROM envoyproxy/envoy-alpine:v1.14-latest
COPY envoy.yaml /etc/envoy/envoy.yaml

envoy.yaml:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 2301 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: greeter_service
                  max_grpc_timeout: 0s
              cors:
                allow_origin_string_match:
                - prefix: "*"
                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
          http_filters:
          - name: envoy.filters.http.grpc_web
          - name: envoy.filters.http.cors
          - name: envoy.filters.http.router
  clusters:
  - name: greeter_service
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    load_assignment:
      cluster_name: cluster_0
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: host.docker.internal
                    port_value: 2302

As I am using an Apple laptop, I use host.docker.internal instead of localhost for address in socket_address.

Here is the whole example:
dockerized_grpc_example.zip
server is supposed to be the folder with the service. In this case, it was a Go gRPC server, but I did not add the source for it.

To start it, install docker and docker-compose. Run docker-compose up after either pasting your Go server source inside the server folder or another server. If you choose to upload a server in another language then you will have to change the Dockerfile inside the server folder.

@virtumonde I have the exact same version of envoy.yml as you. It works perfectly on iOS but not on Android emulator. I get an error with the message Http response at 400 or 500 level.

In the Flipper logs, I can see this stacktrace when the call is being sent.

53  22:24:21.027    unknown:ReactContextBaseJavaModule      Unhandled SoftException
java.lang.RuntimeException: Catalyst Instance has already disappeared: requested by WebSocketModule
    at com.facebook.react.bridge.ReactContextBaseJavaModule.getReactApplicationContextIfActiveOrWarn(ReactContextBaseJavaModule.java:67)
    at com.facebook.react.modules.websocket.WebSocketModule.sendEvent(WebSocketModule.java:62)
    at com.facebook.react.modules.websocket.WebSocketModule.access$100(WebSocketModule.java:40)
    at com.facebook.react.modules.websocket.WebSocketModule$1.onMessage(WebSocketModule.java:190)
    at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:323)
    at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:219)
    at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:105)
    at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:274)
    at okhttp3.internal.ws.RealWebSocket$2.onResponse(RealWebSocket.java:214)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:923)

EDIT (SOLVED)

I was calling the server (Envoy) with http://localhost:8080 in my App.tsx. It works well on iOS. But I had forgotten that the host is not at localhost but 10.0.2.2 on Android 🤦🏽‍♂️.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dv29 picture dv29  ·  6Comments

graup picture graup  ·  4Comments

oferb picture oferb  ·  5Comments

developerlaoz picture developerlaoz  ·  3Comments

verihelp-vaibhav picture verihelp-vaibhav  ·  5Comments