Skip to content

x/net/http2: make Transport check whether a GET Request.Body has any bytes before sending stream? #18891

@kalbasit

Description

@kalbasit

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)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/kalbasit/code"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.7.5/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.7.5/libexec/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/ty/mr64q0m92n98g9lkdrthg2qc0000gn/T/go-build293044907=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"

What did you do?

https://play.golang.org/p/uwnSRGt27v

package main

import (
	"bytes"
	"crypto/tls"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)

func main() {
	c := http.Client{}

	// According to the CloudFront documentation for a request behavior, if the
	// request is GET and includes a body, it returns a 403 Forbidden. See the
	// 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))
	if err != nil {
		log.Fatalf("error creating the request: %s", err)
	}

	res, err := c.Do(r)
	if err != nil {
		log.Fatalf("error doing the request: %s", err)
	}
	io.Copy(ioutil.Discard, res.Body)
	res.Body.Close()

	log.Printf("response status for an HTTP/2 request: %s", res.Status)

	// doing the same request without HTTP/2 does work
	c.Transport = &http.Transport{
		TLSNextProto: map[string]func(string, *tls.Conn) http.RoundTripper{},
	}
	r, err = http.NewRequest("GET", "https://d1ytf8d9p4nfnz.cloudfront.net/optivpaid/optivpaid.js?cb=847742584", ioutil.NopCloser(&body))
	if err != nil {
		log.Fatalf("error creating the request: %s", err)
	}

	res, err = c.Do(r)
	if err != nil {
		log.Fatalf("error doing the request: %s", err)
	}
	io.Copy(ioutil.Discard, res.Body)
	res.Body.Close()

	log.Printf("response status for an HTTP/1 request: %s", res.Status)
}

What did you expect to see?

% go run main.go
2017/02/01 17:27:31 response status for an HTTP/2 request: 200 OK
2017/02/01 17:27:32 response status for an HTTP/1 request: 200 OK

What did you see instead?

% go run main.go
2017/02/01 17:27:31 response status for an HTTP/2 request: 403 Forbidden
2017/02/01 17:27:32 response status for an HTTP/1 request: 200 OK

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions