Skip to content

net/http: Several 100-continue #22128

Closed
Closed
@2at2

Description

@2at2

Hi!
I send request to some server and i have a trouble with several 100-continue responses.

What version of Go are you using (go version)?

go version go1.9 darwin/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/..."
GORACE=""
GOROOT="/Users/.../go1.9"
GOTOOLDIR="/Users/.../go1.9/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/kz/4rf1vvhj2kb910mwtq44qzvr0000gn/T/go-build703834570=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

libcurl example:

curl -i https://*** -H 'Authorization: Basic ***' -H 'Expect: 100-continue' --data 'some content' -v
***
> POST /secure/gateway HTTP/1.1
> Host: ***
> User-Agent: curl/7.54.0
> Accept: */*
> Authorization: Basic ***
> Expect: 100-continue
> Content-Length: 12
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 100 Continue
HTTP/1.1 100 Continue

* We are completely uploaded and fine
< HTTP/1.1 100 Continue
HTTP/1.1 100 Continue

< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Wed, 04 Oct 2017 10:48:22 GMT
Date: Wed, 04 Oct 2017 10:48:22 GMT
< Content-Type: text/xml
Content-Type: text/xml
< Connection: close
Connection: close
< Transfer-Encoding: chunked
Transfer-Encoding: chunked

In example you see two HTTP/1.1 100 Continue

GO 1.9 example:

func main() {
	content := bytes.NewReader([]byte("my super body"))

	request, err := http.NewRequest("POST", "***", content)

	if err != nil {
		panic(err)
	}

	request.Header = make(http.Header)
	request.Header.Set("Authorization", "Basic ***")
	request.Header.Set("Expect", "100-continue")
	
        client := &http.Client{}
	resp, err := client.Do(request)

	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	_, err = ioutil.ReadAll(resp.Body)

	if err != nil {
		panic(err)
	}

	fmt.Println(resp.StatusCode)
	fmt.Println(resp.Status)
}

Result of this example:

100
100 Continue

What did you expect to see?

200
200 Ok

What did you see instead?

100
100 Continue

I found problem in src/net/http/transport.go:1698

What do you think about:

diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 6a89392a99..9f85f07700 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -1715,13 +1715,17 @@ func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTr
 			close(rc.continueCh)
 		}
 	}
-	if resp.StatusCode == 100 {
-		pc.readLimit = pc.maxHeaderResponseSize() // reset the limit
-		resp, err = ReadResponse(pc.br, rc.req)
-		if err != nil {
-			return
+
+	for {
+		if resp.StatusCode == 100 {
+			pc.readLimit = pc.maxHeaderResponseSize() // reset the limit
+			resp, err = ReadResponse(pc.br, rc.req)
+			if err != nil {
+				return
+			}
 		}
 	}
+
 	resp.TLS = pc.tlsState
 	return
 }

I know endless cycle it's not good idea =)

UPD: The similar problem https://stackoverflow.com/questions/22818059/several-100-continue-received-from-the-server . Request to an IIS 7.5 server.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions