TUN-5160: Set request.ContentLength when this value is in request header
This commit is contained in:
parent
d7da74cb9e
commit
470a85e65d
|
@ -180,6 +180,20 @@ func buildHTTPRequest(connectRequest *quicpogs.ConnectRequest, body io.Reader) (
|
||||||
req.Header.Add(httpHeaderKey[1], metadata.Val)
|
req.Header.Add(httpHeaderKey[1], metadata.Val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Go's http.Client automatically sends chunked request body if this value is not set on the
|
||||||
|
// *http.Request struct regardless of header:
|
||||||
|
// https://go.googlesource.com/go/+/go1.8rc2/src/net/http/transfer.go#154.
|
||||||
|
if err := setContentLength(req); err != nil {
|
||||||
|
return nil, fmt.Errorf("Error setting content-length: %w", err)
|
||||||
|
}
|
||||||
stripWebsocketUpgradeHeader(req)
|
stripWebsocketUpgradeHeader(req)
|
||||||
return req, err
|
return req, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setContentLength(req *http.Request) error {
|
||||||
|
var err error
|
||||||
|
if contentLengthStr := req.Header.Get("Content-Length"); contentLengthStr != "" {
|
||||||
|
req.ContentLength, err = strconv.ParseInt(contentLengthStr, 10, 64)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -292,6 +293,107 @@ func (moc *mockOriginProxyWithRequest) ProxyHTTP(w ResponseWriter, r *http.Reque
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildHTTPRequest(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
name string
|
||||||
|
connectRequest *quicpogs.ConnectRequest
|
||||||
|
req *http.Request
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "check if http.Request is built correctly with content length",
|
||||||
|
connectRequest: &quicpogs.ConnectRequest{
|
||||||
|
Dest: "http://test.com",
|
||||||
|
Metadata: []quicpogs.Metadata{
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHeader:Cf-Cloudflared-Proxy-Connection-Upgrade",
|
||||||
|
Val: "Websocket",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHeader:Content-Length",
|
||||||
|
Val: "514",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHeader:Another-Header",
|
||||||
|
Val: "Misc",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHost",
|
||||||
|
Val: "cf.host",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpMethod",
|
||||||
|
Val: "get",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
req: &http.Request{
|
||||||
|
Method: "get",
|
||||||
|
URL: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "test.com",
|
||||||
|
},
|
||||||
|
Proto: "HTTP/1.1",
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
Header: http.Header{
|
||||||
|
"Another-Header": []string{"Misc"},
|
||||||
|
"Content-Length": []string{"514"},
|
||||||
|
},
|
||||||
|
ContentLength: 514,
|
||||||
|
Host: "cf.host",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "if content length isn't part of request headers, then it's not set",
|
||||||
|
connectRequest: &quicpogs.ConnectRequest{
|
||||||
|
Dest: "http://test.com",
|
||||||
|
Metadata: []quicpogs.Metadata{
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHeader:Cf-Cloudflared-Proxy-Connection-Upgrade",
|
||||||
|
Val: "Websocket",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHeader:Another-Header",
|
||||||
|
Val: "Misc",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpHost",
|
||||||
|
Val: "cf.host",
|
||||||
|
},
|
||||||
|
quicpogs.Metadata{
|
||||||
|
Key: "HttpMethod",
|
||||||
|
Val: "get",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
req: &http.Request{
|
||||||
|
Method: "get",
|
||||||
|
URL: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "test.com",
|
||||||
|
},
|
||||||
|
Proto: "HTTP/1.1",
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
Header: http.Header{
|
||||||
|
"Another-Header": []string{"Misc"},
|
||||||
|
},
|
||||||
|
ContentLength: 0,
|
||||||
|
Host: "cf.host",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
req, err := buildHTTPRequest(test.connectRequest, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
test.req = test.req.WithContext(req.Context())
|
||||||
|
assert.Equal(t, test.req, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (moc *mockOriginProxyWithRequest) ProxyTCP(ctx context.Context, rwa ReadWriteAcker, tcpRequest *TCPRequest) error {
|
func (moc *mockOriginProxyWithRequest) ProxyTCP(ctx context.Context, rwa ReadWriteAcker, tcpRequest *TCPRequest) error {
|
||||||
rwa.AckConnection()
|
rwa.AckConnection()
|
||||||
io.Copy(rwa, rwa)
|
io.Copy(rwa, rwa)
|
||||||
|
|
Loading…
Reference in New Issue