Open begoat opened 6 years ago
Hi @begoat,
Thanks for raising. Will try to look into it today. Is there anything specific about your react-native
setup or is it similar to the standard react-native setup?
I setup typescript workflow following this tutorial Thanks in advance. :)
Hi @begoat,
I can reproduce the problem but I do not have a fix yet. It appears that react-native does not allow the http
or https
modules from node to be imported. Because they are declared as top level imports rather than imported lazily, react-native errors as not being able to find them. I'll continue digging into.
:)
Hi! I'm also looking into using this lib with react native.
React native is more browser-like than node-like. It should support fetch and XMLHttpRequest, see https://facebook.github.io/react-native/docs/network.html
Node transport is the last one tried by the factory. So it should select fetch which is first and as a fallback possibly XMLHttpRequest, but not node http.
The quesition is: is there a problem with the detection code itself, or is the detection code failing because of some missing sub-feature of fetch/XMLHttpRequest in RN?
Did you two find out more during debugging? Any hints, where the problem is?
The issue is with RN. It's fetch API implementation does not support streaming: https://github.com/facebook/react-native/issues/9629
Thank you for the hint. I guess, they don't support overrideMimeType, too.
So the remaining options are websockets like in https://github.com/improbable-eng/grpc-web/pull/137 with polling fallback. Or binding the native platform clients of grpc in RN.
The issue is two fold.
RN appears to traverse the import tree and flags up any missing imports. Because the imports are traversed we reach a statement attempting to import http
which is not available on RN. An error is displayed.
The fetch transport does not fully support the features used by grpc-web as mentioned above. Websockets should help alleviate this problem.
I would not recommend Websockets for Mobile; it drains your battery really fast. One benifits of gRPC is its efficiency I.e better on your battery. The best option for RN is to bind to the native gRPC implementations.
Yeah, currently I use both grpc-java and grpc-objectiveC in my react-native project instead. It won't take too much time to implement them and it works well.
@easyCZ, Did you mean grpc-web wouldn't used on react-native?
@easyCZ can we look at migrating away from this http client and into something that react-native will support?
When I did look into this there has been absolutely no way to support grpc in RN. Every option I checked did not work because details have not been implemented in RN. Although they are writing that they support the necessary things in their docs, there are issues open that say: detail xyz is implemented different from the spec/not implemented. So you would probably have to send PRs zo RN first. I just want to throw this hint into the discussion so you can check up front and not when you‘ll have spent a lot of time on this 😉
Thanks Rob!
@RobIsHere did you try this? https://github.com/tradle/react-native-http
No. But the readme says adapted from stream-http which say „It tries to match Node's API and behavior as closely as possible, but some features aren't available, since browsers don't give nearly as much control over requests.“ That’s the problem. RN stuff works like browsers. Grpc-web would be the only way to do it. But as I understood that‘s not yet available.
@begoat @easyCZ After many frustrating hours I got this library working in React Native yesterday using a mix of https://github.com/tradle/rn-nodeify and the following custom transport (based on the xhr one).
As already noted React Native has support for the Fetch API but does not support response.body.getReader() or response.arrayBuffer() so there is no way to get the response as raw bytes. I thought I'd be able to get it working with response.blob()
and then FileReader.readAsDataURL
but I couldn't seem to get the base64 string back into a Uint8Array
without it being corrupted.
The transport below is based on the XHR transport with the following changes:
import { Metadata } from 'grpc-web-client/dist/metadata';
import {
Transport,
TransportOptions,
} from 'grpc-web-client/dist/transports/Transport';
import detach from 'grpc-web-client/dist/detach';
declare const XMLHttpRequest: any;
class XHR implements Transport {
options: TransportOptions;
xhr: any = null;
metadata: Metadata | null = null;
constructor(transportOptions: TransportOptions) {
this.options = transportOptions;
}
onLoadEvent() {
const result = new Uint8Array(this.xhr.response);
detach(() => {
this.options.onChunk(result);
});
detach(() => {
this.options.onEnd();
});
}
onStateChange() {
if (this.xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
detach(() => {
this.options.onHeaders(
new Metadata(this.xhr.getAllResponseHeaders()),
this.xhr.status
);
});
}
}
sendMessage(msgBytes: Uint8Array) {
this.xhr.send(msgBytes);
}
finishSend() {}
start(metadata: Metadata) {
this.metadata = metadata;
const xhr = new XMLHttpRequest();
this.xhr = xhr;
xhr.open('POST', this.options.url);
(xhr as any).responseType = 'arraybuffer';
this.metadata.forEach((key, values) => {
xhr.setRequestHeader(key, values.join(', '));
});
xhr.addEventListener('readystatechange', this.onStateChange.bind(this));
xhr.addEventListener('loadend', this.onLoadEvent.bind(this));
xhr.addEventListener('error', (err: any) => {
detach(() => {
this.options.onEnd(err.error);
});
});
}
cancel() {
this.xhr.abort();
}
}
export default function xhrTransport(options: TransportOptions): Transport {
return new XHR(options);
}
Hope this helps someone 😄
Thanks for the contribution!
Could you please consider raising this as pull request and we can look to get it integrated?
On Tue, 21 Aug 2018, 09:53 Jon Bretman, notifications@github.com wrote:
@begoat https://github.com/begoat @easyCZ https://github.com/easyCZ After many frustrating hours I got this library working in React Native yesterday using a mix of https://github.com/tradle/rn-nodeify and the following custom transport (based on the xhr one).
As already noted React Native has support for the Fetch API but does not support response.body.getReader() or response.arrayBuffer() so there is no way to get the response as raw bytes. I thought I'd be able to get it working with response.blob() and then FileReader.readAsDataURL but I couldn't seem to get the base64 string back into a Uint8Array without it being corrupted.
The transport below is based on the XHR transport with the following changes:
- removed overrideMimeType as this is not supported in React Native
- responseType is set to 'arraybuffer'
- not listening for the 'progress' event - this never seems to fire
- due to the previous point the response body is read in the 'loadend' handler
import { Metadata } from 'grpc-web-client/dist/metadata';import { Transport, TransportOptions, } from 'grpc-web-client/dist/transports/Transport';import detach from 'grpc-web-client/dist/detach'; declare const XMLHttpRequest: any; class XHR implements Transport { options: TransportOptions; xhr: any = null; metadata: Metadata | null = null;
constructor(transportOptions: TransportOptions) { this.options = transportOptions; } onLoadEvent() { const result = new Uint8Array(this.xhr.response); detach(() => { this.options.onChunk(result); }); detach(() => { this.options.onEnd(); }); } onStateChange() { if (this.xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) { detach(() => { this.options.onHeaders( new Metadata(this.xhr.getAllResponseHeaders()), this.xhr.status ); }); } } sendMessage(msgBytes: Uint8Array) { this.xhr.send(msgBytes); } finishSend() {} start(metadata: Metadata) { this.metadata = metadata; const xhr = new XMLHttpRequest(); this.xhr = xhr; xhr.open('POST', this.options.url); (xhr as any).responseType = 'arraybuffer'; this.metadata.forEach((key, values) => { xhr.setRequestHeader(key, values.join(', ')); }); xhr.addEventListener('readystatechange', this.onStateChange.bind(this)); xhr.addEventListener('loadend', this.onLoadEvent.bind(this)); xhr.addEventListener('error', (err: any) => { detach(() => { this.options.onEnd(err.error); }); }); } cancel() { this.xhr.abort(); }
} export default function xhrTransport(options: TransportOptions): Transport { return new XHR(options); }
Hope this helps someone 😄
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/improbable-eng/grpc-web/issues/141#issuecomment-414601236, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMN-fo068v546K0rrFfTKcjmCV4RxTOks5uS8pzgaJpZM4SA2OM .
@jonnyreeves Yeh sure, probably won't have time for another week or so though. In the meantime I will continue to test out my solution on the app I'm working on. Haven't tried it on Android yet... 😟
Lets recap; with the transport provided by @jonbretman, we could add support for React Native? Is that correct? Does anything else need to be done?
@johanbrandhorst, that's correct for support in React Native
I’m sorry I haven’t had time to look at this yet. It’s also worth noting that I haven’t tested this on Android so it might be just an iOS thing.
What I can say if we’re now successfully using this on iOS with no issues so pretty confident it works.
On Mon, 10 Sep 2018 at 01:48, linjson notifications@github.com wrote:
@johanbrandhorst https://github.com/johanbrandhorst, that's correct for support in React Native
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/improbable-eng/grpc-web/issues/141#issuecomment-419758134, or mute the thread https://github.com/notifications/unsubscribe-auth/ABl_cUwHpIeZUX0vMt_Dty5bar40_pEcks5uZbbGgaJpZM4SA2OM .
-- Jon Bretman
mobile: 0774 555 7381 email: jon.bretman@gmail.com
@jonbretman that is very exciting to hear. Would you be interested in contributing this transport to the project?
I would but am just super busy right now. Might have some time over the next few weeks.
Hey all, you seem to be some of the only ones running into my issue. Currently trying to use web3-providers-http
in a React-Native app, but the build fails because the http
module can't be imported. When I install it directly, the corresponding folder is added to node_modules
, but the main index.js
file is not installed, so it fails.
Are there really no work-arounds to let us use that module? Having to rewrite this provider to use a different request solution would be a real drag.
@john-osullivan #265 provides a solution by extracting the Node HTTP Transport out from the core project and into a separate module.
FYI, I'm able to use @improbable-eng/grpc-web
in React Native by using the @improbable-eng/grpc-web-node-http-transport
transport.
In order for that transport to work in RN, I had to:
buffer
stream-http
https-browserify
rn-cli-config.js
:
extraNodeModules: {
buffer: require.resolve('buffer/'),
http: require.resolve('stream-http'),
https: require.resolve('https-browserify')
}
index.js
file:
global.Buffer = require('buffer').Buffer;
My main source for getting to this result was: https://github.com/parshap/node-libs-react-native
Awesome, thanks for posting this. It would be useful to create a react native example in the repo. Would you be interested in contributing? I'm happy to walk you through the contribution if needed.
Unfortunately I don't have time for this now. Sorry.
With #458 I was able to get gRPC-WEB working with RN. Looks pretty similar to what @jonbretman did.
Any update to this? I haven't been able to get any of these solutions to work. The 'grpc-web-client' no longer has any of those files in list and bourquep's change results in errors. Would be nice to have built in support without hacking around the issue.
@mikebm You could take a look at https://github.com/improbable-eng/grpc-web/tree/master/client/grpc-web-react-native-transport
hello guys! Thank you for such hard work around gRPC support in RN!
I have issue with implementation, connection creates - but event onMessage
doesn't triggers at all. Nothing shows in console at all in RN, but wireshark shows, that data flows correctly, but i can't check what kind of data because it's encoded with SSL.
I've tried with ReactNativeTransport
and NodeHttpTransport
, according to @bourquep instructions.
I have separate file with NodeHttpTransport
implementation which works correctly in pure JS without any frameworks, so, i pretty sure, that our backend works well.
Any clues?
This is my app info:
"@improbable-eng/grpc-web": "^0.12.0",
"@improbable-eng/grpc-web-node-http-transport": "^0.12.0",
"@improbable-eng/grpc-web-react-native-transport": "^0.12.0",
"expo": "~36.0.0",
hello guys! Thank you for such hard work around gRPC support in RN! I have issue with implementation, connection creates - but event
onMessage
doesn't triggers at all. Nothing shows in console at all in RN, but wireshark shows, that data flows correctly, but i can't check what kind of data because it's encoded with SSL.I've tried with
ReactNativeTransport
andNodeHttpTransport
, according to @bourquep instructions.I have separate file with
NodeHttpTransport
implementation which works correctly in pure JS without any frameworks, so, i pretty sure, that our backend works well.Any clues?
This is my app info:
"@improbable-eng/grpc-web": "^0.12.0", "@improbable-eng/grpc-web-node-http-transport": "^0.12.0", "@improbable-eng/grpc-web-react-native-transport": "^0.12.0", "expo": "~36.0.0",
Did you ever figure this one out?
Yeah, currently I use both grpc-java and grpc-objectiveC in my react-native project instead. It won't take too much time to implement them and it works well.
Hi, can you please suggest me a proper document on gRPC on react native
Yeah, currently I use both grpc-java and grpc-objectiveC in my react-native project instead. It won't take too much time to implement them and it works well.
Hi, can you please suggest me a proper document on gRPC on react native
https://reactnative.dev/docs/native-modules-ios https://reactnative.dev/docs/native-modules-android https://grpc.io/docs/languages/java/quickstart https://grpc.io/docs/languages/objective-c/basics
Hope this can help. And some comments above also mentioned some promising workaround that deserve a try.
Good luck.
I tried grpc-web today. But unfortunately errors occurred when send request. The error log is cannot resolve http module from node_module/grpc-web-client/dist/transports/nodeHttp.js. The version of grpc-web-client is 0.5.0 which is uploaded 3 days ago.
I try to install http npm package, but another error shows that the node_modules/http/package.json was successfully found but this package itself specifies a 'main' module field that couldn't be found.
I also try to install some browserified package instead for example stream-http and change the nodeHttp.js file's requirement, but seems that I will do many serious tweak.
Could someone give me some more suggestions? :)