-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
x/net/http2: make Transport check whether a GET Request.Body has any bytes before sending stream? #18891
Comments
Same result if you use http.NoBody as well. Using http.NoBody--- s1 2017-02-01 18:35:44.000000000 -0700
+++ s2 2017-02-01 18:36:52.000000000 -0700
@@ -17,7 +17,7 @@
// documentation here:
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#RequestCustom-get-body
var body bytes.Buffer
- r, err := http.NewRequest("GET", "https://d1ytf8d9p4nfnz.cloudfront.net/optivpaid/optivpaid.js?cb=847742584", ioutil.NopCloser(&body))
+ r, err := http.NewRequest("GET", "https://d1ytf8d9p4nfnz.cloudfront.net/optivpaid/optivpaid.js?cb=847742584", http.NoBody)
if err != nil {
log.Fatalf("error creating the request: %s", err)
} 2017/02/01 18:35:02 response status for an HTTP/2 request: 403 Forbidden
2017/02/01 18:35:02 response status for an HTTP/1 request: 200 OK Using nil as the bodySetting the body explicitly to nil works though. 2017/02/01 18:35:13 response status for an HTTP/2 request: 200 OK
2017/02/01 18:35:13 response status for an HTTP/1 request: 200 OK /cc @bradfitz |
@odeke-em, thanks. The HTTP/2 trace is:
I guess we could make the http2 package recognize http.NoBody. We can do that for Go 1.9. (Too late for Go 1.8, especially as it's not a regression.) @kalbasit, there's a simpler fix: use I'm kinda surprised CloudFront distinguishes where the END_STREAM is. But fair enough. We could also investigate doing the 1-byte Body.Read check in http2 (which was removed and restored during Go 1.8 in 6e36811). But it was removed because it kept causing problems and is hard to get right. @kalbasit, how did this happen for you? I assume this is a reduction of a bigger program. What is the concrete type of the body in your actual case? Is it all composed of standard library Readers/Closers, or is it some custom type? |
@bradfitz We have a proxy server that does a clone of the incoming request to the outgoing request, very similar to what go/src/net/http/httputil/reverseproxy.go Lines 152 to 201 in b48c419
|
here's the entire (real function) that prepares an outgoing request from the incoming request with the workaround in place.
|
@kalbasit, yeah, that sounds fine. The other thing you can do is read a byte in your proxy to see if there's actually a byte there. If not (if you get 0, EOF right away), then set the body to nil. If you do get a byte, stitch back your read byte with the remainder using io.MultiReader and set that as your output Request.Body. |
@bradfitz thanks for the tip, I'll give that a try. |
CL https://golang.org/cl/37542 mentions this issue. |
CL https://golang.org/cl/45993 mentions this issue. |
CL https://golang.org/cl/46000 mentions this issue. |
Updates golang/go#18891 Change-Id: I866862d805dc1757b27817ddb30cf22dc48ac3ff Reviewed-on: https://go-review.googlesource.com/45993 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Okay, for Go 1.9, http2 will recognize http.NoBody as if it were nil. For Go 1.10 we can consider whether there are any cases warranting us to reconsider the decision to not do the 1-byte read test to see if a non-nil ReadCloser is actually empty. |
Updates http2 to x/net/http2 git rev 973f3f3 for: http2: make Transport treat http.NoBody like it were nil https://golang.org/cl/45993 Updates #18891 Change-Id: I846ccf286992ed2c6249014e51fdeb40b35e50ed Reviewed-on: https://go-review.googlesource.com/46000 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Happy New Year @bradfitz! How are we doing here? At least x/net/http2 now recognizes http.NoBody so perhaps we can adjust the title accordingly Perhaps we should punt this for Go1.11 since this issue hasn't gotten much attention in the cycle. In regards to "not doing the 1-byte read test to see if a non-nil ReadCloser is actually empy"
// for bytes.Buffer and strings.Reader
if lener, ok := body.(interface{
Len() int
}); ok {
return lener.Len() > 0
}
// Any seekable readers e.g os.File
if seeker, ok := body.(io.Seeker); ok {
n, err := seeker.Seek(1, io.SeekStart)
if err == nil && n > 0 {
defer seeker.Seek(-n, io.SeekCurrent)
}
return err == nil && n > 0
}
// For the rest no option but to try to read the single byte what do you think? |
Updates golang/go#18891 Change-Id: I866862d805dc1757b27817ddb30cf22dc48ac3ff Reviewed-on: https://go-review.googlesource.com/45993 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
What version of Go are you using (
go version
)?go version go1.7.5 darwin/amd64 (also tested on linux)
What operating system and processor architecture are you using (
go env
)?What did you do?
https://play.golang.org/p/uwnSRGt27v
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: