Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transport options (variant B) #261

Closed

Conversation

MOZGIII
Copy link

@MOZGIII MOZGIII commented Oct 19, 2018

See #103
This better captures the idea I poposed at #103. It's also simpler than #260 and users have to opt-in to specify custom tranport.

@MOZGIII MOZGIII changed the title Added support for specifying custom options for fetch transport Transport options (variant B) Oct 19, 2018
Copy link
Contributor

@johanbrandhorst johanbrandhorst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This I like!

ts/src/transports/fetch.ts Show resolved Hide resolved
@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

I noticed some tests failed - and the reason seems to be infrastructure issue, not the code issue.
Btw, speaking of tests. The testing setup used here is not trivial, and I didn't add any new tests in this PR so far. Is it ok? If not - please help me with this.

@johanbrandhorst
Copy link
Contributor

I'm afraid to say some of the tests in our CI setup are a bit flaky, I will rerun them if there appears to be something obviously wrong. It does raise a point though, could you add a test which just shows how to use this new fetch option functionality (and test that it works!)?

@johanbrandhorst
Copy link
Contributor

Also see #259. @jonny-improbable I think we need to get Chrome-42 out sooner rather than later.

@johanbrandhorst
Copy link
Contributor

I've opened #262 to deal with the CI failure (I hope)

@@ -54,7 +55,8 @@ export function runWithHttp1AndHttp2(cb: (config: TestConfig) => void) {

export function runWithSupportedTransports(cb: (transport: grpc.TransportConstructor | undefined) => void) {
const transports: {[key: string]: grpc.TransportConstructor | undefined} = {
"defaultTransport": undefined
"defaultTransport": undefined,
"fetchWithOptions": fetchRequestWithOptions({}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we may need to add this key to some test cases as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be used by all test cases as a way to provide transport - so it sohlud do the trick. Testing setup is rather complictaed, but seems to be prepared for testing custom transports like this. Would like a comment from @MarcusLongmuir on this.

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

(I think) I added the new API to tests. Don't really know if it's the correct way - let's see what CI does in response to this.

@johanbrandhorst
Copy link
Contributor

The tests probably won't pass until #262 is merged regardless, but we can force this through if everything but Chrome-42 passes.

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

What's going on with tests? They seems to be stuck - is it Travis CI that's not scheduling them to run?

@johanbrandhorst
Copy link
Contributor

I think it's just limited to 5 concurrent runners per project, and some of the runners are taken up by my #262. Please wait :).

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

From the previous test run: Safari now has some strange failures - https://travis-ci.org/improbable-eng/grpc-web/builds/443570174
Can you please take a look? Doesn't seem to be caused by my changes.

@johanbrandhorst
Copy link
Contributor

I've restarted the safari tests. As you say, they shouldn't be affected by your changes.

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

I uncovered another problem - transport implementations are not exported. I think I have to add a way to use this fetchRequestWithOptions thing from outside explicitly.

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

And it seems I need further help with tests - there are some failures in firefox when I test my fetchWithOptions implementation - and this is probably due to firefox not properly supporting the fetch in the first place (with the older versions). We probably need to somhow skip the tests for unsupported browsers.
I think my code is ok since it's only some tests that are failing.

@johanbrandhorst
Copy link
Contributor

If Firefox should default to MozXHR AFAIK - if we've broken that we need to fix it. Are there tests running on Firefox with fetch that shouldn't be? I'm not very familiar with the tests either I'm afraid, but you should be able to run it locally I assume?

@johanbrandhorst
Copy link
Contributor

If you want, you can try reaching out to @MarcusLongmuir or @jonny-improbable or @easyCZ on the grpc-web slack (see README.md).

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

I have to step out now, hopefully they'll see this PR and comment before I get back.

@jonny-improbable
Copy link
Contributor

Hmm, I have some reservations with this approach. The main reason being that one of the goals of grpc-web is to provide an abstraction over the underlying browser technology; hence why we have both fetch and xhr based transports.

The problem with this approach is that the caller is specifying the concrete transport to use; whilst fetch will work fine in Chrome, it would fail if executed in Firefox because streaming of response bodies is currently behind a feature flag (see here).

In the past I've considered adding a credentials field to the TransportOptions object and then implementing some logic in the XhrTransport to set the withCredentials prop accordingly; however given that we now support a WebSocket transport, such a credentials option no longer applies to all transports.

My initial thinking might be to create a clear distinction between the 2 types of transport we have: 'Http' based and 'Socket' based (where the HttpTransport is an abstraction over fetch and xhr based on the capabilities of the host browser). Once this has been achieved we can have different TransportOptions for each type of transport.

A further step could be to make the DefaultTransportFactory be injectable so the user can make any 'global' transport configuration without having to configure each rpc call site.

WDYT?

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

Well, the idea of this PR is to utilize the pre-existing ability to specify custom transport to fine-tune the underlying transport. The real goal here is to have the ability to fine-tune the transports (in particular - just the fetch transport). This brings me to the point: even if the transpord it chosen automatically, I'd like to have a way to file-tune it's internal to better fit my needs. I also like the transport autodetection, but the ability to force the usage of a specific transport and to control it would be a must have as well.
We were able to quickly test (and ditch, cause it didn't work as we expected) the setup with credentials: 'include' in our internal dev process using the custom fetch transport copied form tree. This would be much better if we could just do it directly, without doing those "smart tricks".
So, it's not just about letting setting just the credentials (though current PR just provides that) - it's about fine-tuning the transport internal implementation.

What you're proposing is all good, but providing knobs (as an opt in - for people that need those, like me when I had that particular usecase) for transport is, I'd say more important. And, since knobs for different transports will be different, a unified interface to all of the possible tweakable parameters is not required - and adding knobs is not therefore blocked by splitting Http/Stream transports.

When interface for setting internal implementation details is ready - additional logic (like unified tweaking for unified Http tranport family) can be build ot not of it; and I'd be happy to see that, but even more I'd love the ability to tweak transports as close and flexible to native APIs as possible.

@johanbrandhorst
Copy link
Contributor

There's something to be said for carefully adding API surface though, and if we can accomplish the same thing with a longer term goal, shouldn't we try that first? If we only need to expose credentials and they can both be shared between Fetch and XHR, lets do that now.

@MOZGIII
Copy link
Author

MOZGIII commented Oct 19, 2018

Sure, why not. Especially that this PR just does that (for fetch), and we can implement simialr thing for XHR. We can also implement a "default" transport "withOptions", that would allow passing credentials, and setting them for fetch/XHR, and either ignoring or thoring an error if it the transport picked is not fetch not XHR. Does this plan seem reasonable?

@jonnyreeves
Copy link
Contributor

jonnyreeves commented Oct 19, 2018 via email

@MOZGIII
Copy link
Author

MOZGIII commented Oct 21, 2018

Superseded by #265

@MOZGIII MOZGIII closed this Oct 21, 2018
jonny-improbable pushed a commit that referenced this pull request Oct 27, 2018
Following on from the conversation in #261 this PR allows the user to configure the behavior of a given Transport, separate from the pre-existing TransportOptions interface which deals with passing request state (ie: host, url, callbacks, etc).

To facilitate this change, the transport option passed to the unary, invoke and client functions is now expected to meet the new grpc.TransportFactory interface, ie: a func which can accept zero or more args and will return a grpc.Transport instance.

```
grpc.unary(BookService.GetBook, {
    request: getBookRequest,
    host: host,
    transport: grpc.HttpTransport({ credentials: 'include' }),
    onEnd: ( /*...*/ )
});
```

Note this results in a breaking change for anyone currently using the Websocket Transport; instead of specifying:

```
transport: gprc.WebsocketTransportFactory
```

They would instead now call:

```
transport: grpc.WebsocketTransport()
```

This change also spurred me to to fix #191 and #141 by extracting the 'Node HTTP' transport out from the gprc-web-client package and into a new module: grpc-web-node-http-client, which will be published to npm separately.

As one thing leads to another, extracting node-grpc-web-node-http-transport led to implement grpc.setDefaultTransport() which allows the user to specify which TransportFactory` should be .invoked if none is supplied in the options.

## Breaking Changes
transport option passed to unary, invoke and client is now expected to by an instance of Transport, not a reference to a function which will return a Transport when invoked.
grpc-web-client no longer auto-selects a suitable transport in a NodeJS environment; users of grpc-web-client in a NodeJS environment will need to depend upon grpc-web-node-http-transport and make use of grpc.setDefaultTranpsport().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants