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
net/http: set response headers on TimeoutHandler timeout #22821
Comments
Of the recommendations, IMO the only thing to do is mention what the default message is. (And for Go2, use a different API that let's you specify content type.) In terms of setting Content-Type, there seem to be two options:
If we choose 1, the new function could be something like
If we choose 2, we could Assuming the API is not added to, removing the default message could be bad user experience - browser returning a 503 without any body might be considered by users as loss of internet connectivity, depending on how clear the browser explains the problem. (It might also be considered backwards incompatible.) |
@bradfitz - this is going in the 1.11 train ? We just need a decision here regarding what is to be done. |
@meirf, it already uses @SamWhited, can you elaborate what the problem was? I'm going to kick this to Unplanned until there's more detail. |
Change https://golang.org/cl/125855 mentions this issue: |
Unfortunately the "real world" code I originally ran into this problem with no longer exists and timeout handler isn't being used in the codebase anymore, however it was part of the REST API, I think, so I'm assuming it was JSON.
Am I doing something foolish then? This suprised me so I threw together this test to check and it is failing as expected. Even if the DetectContentType call were happening at some higher level in the stack, this was causing problems with prod for me so maybe wherever it happens isn't always triggered (I haven't looked yet to see where this might happen): var contentTypeTests = [...]struct {
body string
contentType string
}{
0: {
body: "",
contentType: "text/html; charset=utf-8",
},
1: {
body: "test",
contentType: "text/plain; charset=utf-8",
},
}
func TestTimeoutHandler(t *testing.T) {
for i, tc := range contentTypeTests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
h := TimeoutHandler(HandlerFunc(func(w ResponseWriter, r *Request) {
time.Sleep(2 * time.Second)
}), time.Second, tc.body)
w := httptest.NewRecorder()
h.ServeHTTP(w, httptest.NewRequest("GET", "/", nil))
const defBody = `<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>`
if s := w.Body.String(); (tc.body == "" && s != defBody) || (tc.body != "" && s != tc.body) {
t.Errorf("Bad body: want=%q, got=%q", tc.body, s)
}
if s := w.HeaderMap.Get("Content-Type"); s != tc.contentType {
t.Errorf("Bad CT: want=%q, got=%q", tc.contentType, s)
}
})
}
}
The handler was replying with a 503, but no content-type header was being set which was expected by a client using the service. I couldn't wrap the handler in something else because WriteHeader had already been called, so there was no good way for me to set a content-type if the timeouthandler fires. |
Updates #22821 Change-Id: I2d0d483538174a90f56c26d99bea89fe9ce4d144 Reviewed-on: https://go-review.googlesource.com/125855 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Andrew Bonventre <andybons@golang.org>
Updates golang#22821 Change-Id: I2d0d483538174a90f56c26d99bea89fe9ce4d144 Reviewed-on: https://go-review.googlesource.com/125855 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Andrew Bonventre <andybons@golang.org>
Is there a plan of action about this request? |
#46721 was marked as a duplicate of this while IMO it was more a feature request: allow timeout response customization. |
(Retitling this issue, since I think the real desire is a way to set Content-Type on timeout.) If we want to give the user more control over the response when a timeout occurs, then I think the right thing to is for the user to provide two Handlers. Something like this, maybe:
I don't know what we'd call TimeoutHandler2. Another possibility would be to call h.ServeHTTPTimeout when present; that'd be a bit clunkier to use, but avoids adding a new function. |
|
I guess either a new constructor #22821 (comment) or a new interface would be required, e.g.: type HandlerWithTimeout interface {
Handler
// ServeTimeout writes timeout error response.
// Use r.Context().Err() to obtain the error value.
ServeTimeout(w ResponseWriter, r *Request)
} see #49119 |
Change https://golang.org/cl/357918 mentions this issue: |
I was recently suprised to discover that
http.TimeoutHandler
returns a blob of HTML ("<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
) as the default message body. It does not attempt to set the appropriate Content-Type header and if you write a response yourself there is no option to set the content type.The documentation says:
It would be nice if the format of the default message could be mentioned in the documentation, the default could be removed, or the Content-Type could be set (or some combination of the above).
/cc @bradfitz
The text was updated successfully, but these errors were encountered: