-
Notifications
You must be signed in to change notification settings - Fork 17
Conversation
Fixes traefik/traefik#1419 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments but mostly questions. :-)
return | ||
} | ||
|
||
if written != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason we're removing this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a set of a header after this initial WriteStatus, which isn't allowed. The only way to do this would be to buffer the entire response, write the content-length, then write the body out. You have to assume that the original handler has already set the content-length. It's unrelated to the actual fix to trailers, but it's definitely not a valid thing to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, interesting, didn't know. For the sake of completeness, is this forbidden by Go (and possibly documented somewhere) or rather an underlying HTTP requirement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did the same a year ago in 1832129
But I had to rollback it to fix an empty response issue in traefik traefik/traefik#476
Any idea on this @tcolgate ?
forward/fwd.go
Outdated
|
||
announcedTrailerKeyCount := len(response.Trailer) | ||
if announcedTrailerKeyCount > 0 { | ||
trailerKeys := make([]string, 0, len(response.Trailer)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it for performance reasons that we don't just append to a nil slice?
forward/fwd.go
Outdated
written, err := io.Copy(newResponseFlusher(w, stream), response.Body) | ||
_, err = io.Copy(newResponseFlusher(w, stream), response.Body) | ||
if err != nil { | ||
ctx.log.Errorf("Error copying upstream response Body: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Body -> body
forward/fwd.go
Outdated
return | ||
} | ||
|
||
response.Body.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping the defer might be preferable in order to allow future reads of the body inside this method without having to think about adjusting this line. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't defer the Close() this is the crux of the problem. You must write trailers after the body is closed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave a comment then so future developers know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can use ioutils.NewReadCloserWrapper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops it's a docker package...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for comment here
I forgot: would it be possible to add a test as well? Thanks! |
@tcolgate any updates on this one? do you think it would be possible to add a test and address the nit-picky comments? :) |
For the sake of completion: vulcand/oxy also has an open PR on this issue: vulcand#27 Unfortunately, it never received maintainer attention. |
It'll be a week or so before I get a chance. Re; oxy, they moved over to
using httputil.ReverseProxy, which has the same problem, and should get the
fix in Go 1.9 hopefully
…On Wed, 31 May 2017, 21:07 Timo Reimann, ***@***.***> wrote:
For the sake of completion: vulcand/oxy also has an open PR on this issue:
vulcand/oxy#27 <vulcand#27>
Unfortunately, it never received maintainer attention.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#15 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAEo88VW7VAO4Xmcj_eMctB6LrDaEC1Bks5r_chygaJpZM4NhVUM>
.
|
@tcolgate thanks for the heads up! whenever you have time. btw, any chance you could assess if you fix might have a positive impact on traefik/traefik#1686? |
Yes, probably. Though it would be good to know the motivation for the
attempted
Content-Length write.
…On Wed, 31 May 2017, 21:53 Timo Reimann, ***@***.***> wrote:
@tcolgate <https://github.com/tcolgate> thanks for the heads up! whenever
you have time.
btw, any chance you could assess if you fix might have a positive impact
on traefik/traefik#1686
<traefik/traefik#1686>?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#15 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAEo8-YNgbYW71Nr629Ja3gyNIM0rhlpks5r_dNcgaJpZM4NhVUM>
.
|
@tcolgate any news on this one ? |
Sorry, not yet, tied up with other stuff at the moment. |
forward/fwd.go
Outdated
return | ||
} | ||
|
||
response.Body.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for comment here
forward/fwd.go
Outdated
} | ||
|
||
//No defer on body close in order to force announce trailer after body close | ||
response.Body.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, we don't need the response to be closed, we just need that the body was read until EOF
https://github.com/golang/go/blob/master/src/net/http/response.go#L96
@tcolgate WDYT about this changes ? |
The writeheader after data has been written is invalid unfortunately (headers are , by definition, only valid at the start of the response). The empty response is likely cause by no write ever having been done on a response before a close in some other path (so you never actually write a status). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big improvement!
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One nit-pick left, but I'll already give my LGTM. :-)
forward/fwd.go
Outdated
@@ -178,6 +190,20 @@ func (f *httpForwarder) serveHTTP(w http.ResponseWriter, req *http.Request, ctx | |||
} | |||
} | |||
written, err := io.Copy(newResponseFlusher(w, stream), response.Body) | |||
if err != nil { | |||
ctx.log.Errorf("Error copying upstream response Body: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still nit-pick, but should still be decapitalized to body. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No description provided.