Python/Core: Regression in grpcio
, error parsing of content-type metadata
#35323
Labels
grpcio
, error parsing of content-type metadata
#35323
What version of gRPC and what language are you using?
For these
grpcio
(python) versions (client side), the problem described below appears or doesn't appear:1.53.0
works1.53.1
works1.53.2
works1.54.0
works1.54.2
works1.54.3
works1.55.3
doesn't work (prior1.55
versions have been yanked)1.56.0
works1.56.2
doesn't work1.57.0
doesn't work1.58.0
doesn't work1.59.0
doesn't work1.60.0
doesn't workWhat operating system (Linux, Windows,...) and version?
Mac or Linux (client)
Linux (server)
What runtime / compiler are you using (e.g. python version or version of gcc)
Python 3.10.7 (also tested with 3.9)
What did you do?
Our python client library makes calls to a gRPC backend deployed behind a GCP load balancer (GCE Ingress on GKE) with GCP Identity Aware Proxy (IAP) enabled. The client authenticates lazily in the sense that it first tries an unauthenticated request/request with cached credentials and if this doesn't work, refreshes credentials and tries again:
For newer versions of
grpcio
, the rpc fails even though the lazy authentication works and the server responds with "the right payload".Minimal working example
We condensed the relevant logic from the client library into this example greeter client:
Click me
What did you expect to see?
What did you see instead?
With a working version, e.g.
grpcio==1.53.0
:With a non-working version, e.g.
grpcio==1.60.0
:What we have discovered so far
1. Wrong content type of response
When unauthenticated, GCP IAP returns content-type
text/html
. This happens even if one includes("accept", "application/grpc")
headers (which we omitted in the minimal example as it doesn't help).See screenshots from developer console showing this
Authenticated request:
Unauthenticated request:
2. Lazy authentication actually always successful!
With
GRPC_VERBOSITY=debug GRPC_TRACE=all
we have figured out that the lazy authentication actually always works and even if the rpc ultimately fails, e.g. withgrpcio==1.60.0
, the server actually returns the correct payload (including "Hi Client").Requests/responses for `grpcio==1.53.0`
First request, without token
Request:
Response:
Second request, with token
Request:
Response:
Requests/responses for `grpcio==1.60.0` which ultimately fails but still shows `"Hi Client"` in the response!
First request, without token
Request:
Response:
Second request, with token
Request:
Response:
Notice the
content-type: application/grpc
,status: 200
andHi Client
!And we see it a couple of times after that:
We wonder why the rpc ultimately fails for
grpc==1.60.0
even though the refreshing of the credentials works and the server responds with"Hi Client"
.3. It works with e.g.
grpcio==1.60.0
if one never makes an unauthenticated requestIf one never makes an unauthenticated request but refreshes credentials before the first call (by uncommenting the first
# self._authenticator.refresh_credentials()
inintercept_unary_unary
), the rpc works for all versions.Anything else we should know about your project / environment?
Thank you!
The text was updated successfully, but these errors were encountered: