grpc-web: Error callback never invoked for some classes of server response.

I have a grpc-web server that is returning 200 OK, and grpc-status / grpc-message, but the client javascript is failing to parse it. The observed behavior is that client requests never receive a completion callback from the library. See the request/response sample below.

The case below is likely related to: https://github.com/google/closure-library/issues/946 , however a quick review of the code suggests there may be more cases like this; unexpected server responses aren’t correctly handled.

Request URL: http://localhost:8090/derp.EchoService/Echo
Request Method: POST
Status Code: 200 OK
Remote Address: 127.0.0.1:8090
Referrer Policy: no-referrer-when-downgrade

Response Headers:
access-control-allow-credentials: true
access-control-allow-origin: null
content-length: 0
content-type: application/grpc-web+proto
date: Thu, 20 Dec 2018 19:25:32 GMT
grpc-message: upstream connect error or disconnect/reset before headers
grpc-status: 14
server: envoy
Provisional headers are shown
Content-Type: application/grpc-web+proto
grpc-timeout: 999m
Origin: null
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
X-Grpc-Web: 1
X-User-Agent: grpc-web-javascript/0.1

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 5
  • Comments: 17

Commits related to this issue

Most upvoted comments

Hi @y3llowcake ! I don’t kown if my problem is in the scope of this issue but here is the explanation: I have a gRPC server written in Go, my proxy is envoy, and I use the JS client of grpc-web in this mode: import_style=commonjs,mode=grpcwebtext.

If my server resturns a gRPC error, the JS Client don’t handle the error. For example, this call returns a valid GRPC error in headers: 50375748-e3057e00-0602-11e9-8608-c7771c2e7601

but my client don’t handle it:

const signUpCall = accountClient.signUp(accountRequest, {}, (err, res) => {
    if (err) {
        console.error(err);
    }
    console.log(res);
});

signUpCall.on('status', status => console.log('status', status));
signUpCall.on('data', d => console.log('data', d));
signUpCall.on('end', d => console.log('end', d));
signUpCall.on('error', d => console.log('error', d));

(In this case, none of my console.log was called…)

What do you think ? 😃 Thanks !

@skyjia Could you let me know what exactly the incorrect configuration was? We have been stuck with this same problem in our app and seem to have a similar environment as you do.

Thanks in advance!

@aberasarte we have figured out the issue. It’s due to an incorrect configuration in our API gateway.

I’m running into the same issue while I’m debugging my implementation of a grpc-web server. If I return an incorrectly encoded response, the grpc-web Javascript client just drops it. Instead, I would expect to get a gRPC error response with code INTERNAL probably? I can provide a more detailed reproduction if that would be useful.

@aberasarte I changed the expose headers and restarted the envoy, this error callback is still never invoked.

expose_headers: grpc-status,grpc-message

package.json:

 "dependencies": {
    "google-protobuf": "^3.10.0",
    "grpc-web": "^1.0.7",
  },
   getUserProfile (accessToken, ouid) {
    const request = new ProtoUserAPI.GetUserProfileRequest()
    request.setOuid(ouid)
    request.setAccessToken(accessToken)

    const metadata = null

    const that = this

    return new Promise((resolve, reject) => {
      that.client.getUserProfile(request, metadata, (err, response) => {
        // #1 never go here when there is an error

        if (err) {
          reject(err.message)
        } else {
          // #2 go here when successful
          resolve(response)
        }
      })
    })
  }

The code never goes to #1 when there is an error reported from underlying gRPC service. I can see the grpc-status and grpc-message headers in HTTP response in Chrome devtool.

However, the code can go to #2 when the RPC call is successful.