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

grpc-web, XhrClientConnection sets certain headers twice #381

Closed
yiransheng opened this issue Nov 3, 2020 · 2 comments
Closed

grpc-web, XhrClientConnection sets certain headers twice #381

yiransheng opened this issue Nov 3, 2020 · 2 comments

Comments

@yiransheng
Copy link

yiransheng commented Nov 3, 2020

XhrClientConnection's implementation may set these http headers twice:

  • Content-Type
  • X-User-Agent
  • X-Grpc-Web

This is problematic, for instance, when running flutter web (in browser platform). I believe it is expected for grpc-web to have this header:

X-Grpc-Web: 1

However, if this is set twice via underlying XHttpRequest api (calling request.setRequestHeader('X-Grpc-Web', '1'); twice) would produce the following instead (in latest Chrome browser):

X-Grpc-Web: 1, 1

...thus breaking the protocol.

Repro steps

  1. Initialize GrpcWebClientChannel client
  2. Make any grpc-web api calls, leave CallOptions.metadata's Content-Type empty

Expected result: grpc-web requests successful

Actual result: indeterminate errors, usually timeout (in my case the api call was interpreted as a native grpc call by envoy proxy)

Details

The offending code:

  1. if (_getContentTypeHeader(metadata) == null) {

When content type metadata from CallOptions is null, XhrClientConnection will fill in some defaults.

  1. sometime later:
    for (final header in metadata.keys) {

It copies metadata into http request headers.

  1. however, immediately after:
    request.setRequestHeader('X-Grpc-Web', '1');

The same header is set again, introducing the erroneous header values described above.

Equivalent compiled javaScript code:

function setHeadersTwice() {
  const xhr = new XMLHttpRequest();
  xhr.open('POST', 'https://example.com');
  xhr.setRequestHeader('X-Grpc-Web', '1');
  xhr.setRequestHeader('X-Grpc-Web', '1');
  xhr.send();
}

Reference form MDN:

Each time you call setRequestHeader() after the first time you call it, the specified text is appended to the end of the existing header's content.

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader

@mraleph
Copy link
Member

mraleph commented Nov 5, 2020

Duplicate of #380

@mraleph mraleph marked this as a duplicate of #380 Nov 5, 2020
@mraleph mraleph closed this as completed Nov 5, 2020
@mraleph
Copy link
Member

mraleph commented Nov 5, 2020

Thanks for the report.

We are going to revert offending change and publish a fixed version of the package, but most likely this is not going to happen earlier than next week.

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

No branches or pull requests

2 participants