Comments (3)
Hi, thanks for your issue! I'm a little confused about exactly what the bug is here. From what I can gather, this is the chain of events:
curl
sends HTTP request to server- gRPC-Gateway handles the request
- The request reaches the gRPC server
- The store ID interceptor runs on the gRPC server, storing an ID in the ctx via
grpc.SetHeader
(not actually sure this works, since the use of the grpc-ecosystem interceptor pattern is making things hard to follow). - The gRPC server handler runs, which sleeps for 1 second, causing the gRPC client to time out the request.
Is this correct? Because as far as I'm concerned there is no way for the server to do anything while the handler is sleeping, and the gRPC client is timing out without waiting for a response. What do you think the gateway is doing wrong here? Nothing has been written on the wire for it to translate, and even if it was, I'm not sure it should.
Perhaps you could start by explaining what you were trying to do, and we can see if there's some other way to do it? I would recommend simplifying your test repo to just the essentials too (I assume the OTel observability stuff isn't necessary to exhibit the issue).
Thanks!
from grpc-gateway.
Hey @johanbrandhorst, thanks for the fast response 🙇♀️ I've trimmed the repo now 😄
I'm a little confused about exactly what the bug is here
It's likely that it's not a bug, more of a misunderstanding on my part on how to achieve my goal.
Perhaps you could start by explaining what you were trying to do
Yes, sorry, I wasn't clear. My goal is two-fold.
- set a maximum amount of time that server handlers are allowed to run. (I thought
runtime.DefaultContextTimeout = 50 ms
achieved this) - send response headers back to clients in the case of errors (which includes the deadline being hit).
The store ID interceptor runs on the gRPC server, storing an ID in the ctx via grpc.SetHeader (not actually sure this works, since the use of the grpc-ecosystem interceptor pattern is making things hard to follow).
What part of the interceptor pattern is hard to follow? I thought this was the standard way of implementing middlewares? I can't think of an easier way of setting headers 🤔
In any case, my issue is that if you remove the time.Sleep
in the handler (i.e. produce a success response) the response header is correctly received by the client. But if i artificially produce a deadline exceeded
error, then the client doesn't get this header.
The gRPC server handler runs, which sleeps for 1 second, causing the gRPC client to time out the request.... Because as far as I'm concerned there is no way for the server to do anything while the handler is sleeping, and the gRPC client is timing out without waiting for a response
This is where i'm seeing cracks on my understanding. I thought that by doing
runtime.DefaultContextTimeout = 50 * time.Millisecond
i was setting a deadline on the server handler, not on the client. Is there a way of setting a deadline on the server?
from grpc-gateway.
Thanks for your explanation. I should have been clearer about what I mean by "client" and "server". In this case, the grpc-gateway is both a server and client. The timeout you configured is on the client side of the grpc-gateway <-> grpc server connection. The client part of the gateway will not wait for the grpc server to respond before terminating the connection. So when you call grpc.SetHeader
on the grpc side, it probably has no way of doing that since it's in the middle of a sleep. Again, I'm not sure what PostMsgReceive
actually does on the interceptor side. I would recommend implementing the interceptors as functions directly instead of using go-grpc-middleware (I say this as a maintainer of go-grpc-middleware). There's no need to involve the complicated interface pattern used there for this simple test.
In any case, if the timeout was on the grpc server side, you might be able to stop processing and send headers, but you wouldn't be able to use a sleep since it pauses the goroutine completely, you'd have to use a select, like so:
select {
case <-time.After(time.Second): // replaces the sleep
case <-ctx.Done():
// call SetHeader here, maybe?
}
I also think, generally, it's going to be hard to intercept timeouts and set headers in the grpc infrastructure. Perhaps you could write a HTTP middleware around the grpc-gateway which can detect certain status codes and set headers appropriately instead?
from grpc-gateway.
Related Issues (20)
- Moving protos out of protoc-gen-openapiv2/options directory to support Python HOT 3
- Grpc gateway project starter script HOT 1
- Support Service doc comments for OpenApi/Swagger generation HOT 4
- [Feature Request] Provide a legit way to override HTTP Response. HOT 7
- How to get HTTP headers in custom Marshaller? HOT 1
- streaming response does not return text/event-stream content-type HOT 14
- Define "CustomHttpPattern" under "google.api.http", using the plug-in protoc-gen-openapiv2 encountered no swagger documentation generated. HOT 1
- Support Protobuf Editions HOT 7
- Dealing with 304 response without printing errors HOT 5
- How to pass the error 400 in fieldmask if a unknow field is send? HOT 1
- google.protobuf.Empty as response serializes to not empty response on REST client depending on request headers HOT 4
- ERROR: Failed to extract ServerMetadata from context HOT 13
- Placement for unique items in array type is located in the wrong place HOT 1
- Support explicit omitempty annotation in proto HOT 1
- gateway to multiple grpc services defined in two different files HOT 3
- bug: URL Query parameter not bind to `Optional` proto message field HOT 5
- How can register multiple gRPC services in `main.go` at the same time? HOT 1
- Feature request: virtual oneof property HOT 3
- Unable to mark the body parameter as REQUIRED when part of the proto message is path param HOT 2
- google.protobuf.Any generated OpenAPI v2 yaml that is potentially incorrect HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from grpc-gateway.