Skip to content

Commit 470a85e

Browse files
TUN-5160: Set request.ContentLength when this value is in request header
1 parent d7da74c commit 470a85e

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

connection/quic.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,20 @@ func buildHTTPRequest(connectRequest *quicpogs.ConnectRequest, body io.Reader) (
180180
req.Header.Add(httpHeaderKey[1], metadata.Val)
181181
}
182182
}
183+
// Go's http.Client automatically sends chunked request body if this value is not set on the
184+
// *http.Request struct regardless of header:
185+
// https://go.googlesource.com/go/+/go1.8rc2/src/net/http/transfer.go#154.
186+
if err := setContentLength(req); err != nil {
187+
return nil, fmt.Errorf("Error setting content-length: %w", err)
188+
}
183189
stripWebsocketUpgradeHeader(req)
184190
return req, err
185191
}
192+
193+
func setContentLength(req *http.Request) error {
194+
var err error
195+
if contentLengthStr := req.Header.Get("Content-Length"); contentLengthStr != "" {
196+
req.ContentLength, err = strconv.ParseInt(contentLengthStr, 10, 64)
197+
}
198+
return err
199+
}

connection/quic_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"math/big"
1414
"net"
1515
"net/http"
16+
"net/url"
1617
"os"
1718
"sync"
1819
"testing"
@@ -292,6 +293,107 @@ func (moc *mockOriginProxyWithRequest) ProxyHTTP(w ResponseWriter, r *http.Reque
292293
return nil
293294
}
294295

296+
func TestBuildHTTPRequest(t *testing.T) {
297+
var tests = []struct {
298+
name string
299+
connectRequest *quicpogs.ConnectRequest
300+
req *http.Request
301+
}{
302+
{
303+
name: "check if http.Request is built correctly with content length",
304+
connectRequest: &quicpogs.ConnectRequest{
305+
Dest: "http://test.com",
306+
Metadata: []quicpogs.Metadata{
307+
quicpogs.Metadata{
308+
Key: "HttpHeader:Cf-Cloudflared-Proxy-Connection-Upgrade",
309+
Val: "Websocket",
310+
},
311+
quicpogs.Metadata{
312+
Key: "HttpHeader:Content-Length",
313+
Val: "514",
314+
},
315+
quicpogs.Metadata{
316+
Key: "HttpHeader:Another-Header",
317+
Val: "Misc",
318+
},
319+
quicpogs.Metadata{
320+
Key: "HttpHost",
321+
Val: "cf.host",
322+
},
323+
quicpogs.Metadata{
324+
Key: "HttpMethod",
325+
Val: "get",
326+
},
327+
},
328+
},
329+
req: &http.Request{
330+
Method: "get",
331+
URL: &url.URL{
332+
Scheme: "http",
333+
Host: "test.com",
334+
},
335+
Proto: "HTTP/1.1",
336+
ProtoMajor: 1,
337+
ProtoMinor: 1,
338+
Header: http.Header{
339+
"Another-Header": []string{"Misc"},
340+
"Content-Length": []string{"514"},
341+
},
342+
ContentLength: 514,
343+
Host: "cf.host",
344+
},
345+
},
346+
{
347+
name: "if content length isn't part of request headers, then it's not set",
348+
connectRequest: &quicpogs.ConnectRequest{
349+
Dest: "http://test.com",
350+
Metadata: []quicpogs.Metadata{
351+
quicpogs.Metadata{
352+
Key: "HttpHeader:Cf-Cloudflared-Proxy-Connection-Upgrade",
353+
Val: "Websocket",
354+
},
355+
quicpogs.Metadata{
356+
Key: "HttpHeader:Another-Header",
357+
Val: "Misc",
358+
},
359+
quicpogs.Metadata{
360+
Key: "HttpHost",
361+
Val: "cf.host",
362+
},
363+
quicpogs.Metadata{
364+
Key: "HttpMethod",
365+
Val: "get",
366+
},
367+
},
368+
},
369+
req: &http.Request{
370+
Method: "get",
371+
URL: &url.URL{
372+
Scheme: "http",
373+
Host: "test.com",
374+
},
375+
Proto: "HTTP/1.1",
376+
ProtoMajor: 1,
377+
ProtoMinor: 1,
378+
Header: http.Header{
379+
"Another-Header": []string{"Misc"},
380+
},
381+
ContentLength: 0,
382+
Host: "cf.host",
383+
},
384+
},
385+
}
386+
387+
for _, test := range tests {
388+
t.Run(test.name, func(t *testing.T) {
389+
req, err := buildHTTPRequest(test.connectRequest, nil)
390+
assert.NoError(t, err)
391+
test.req = test.req.WithContext(req.Context())
392+
assert.Equal(t, test.req, req)
393+
})
394+
}
395+
}
396+
295397
func (moc *mockOriginProxyWithRequest) ProxyTCP(ctx context.Context, rwa ReadWriteAcker, tcpRequest *TCPRequest) error {
296398
rwa.AckConnection()
297399
io.Copy(rwa, rwa)

0 commit comments

Comments
 (0)