Revert "TUN-8592: Use metadata from the edge to determine if request body is empty for QUIC transport"
This reverts commit e2064c820f
.
This commit is contained in:
parent
92e0f5fcf9
commit
f407dbb712
|
@ -42,26 +42,12 @@ const (
|
||||||
HTTPMethodKey = "HttpMethod"
|
HTTPMethodKey = "HttpMethod"
|
||||||
// HTTPHostKey is used to get or set http Method in QUIC ALPN if the underlying proxy connection type is HTTP.
|
// HTTPHostKey is used to get or set http Method in QUIC ALPN if the underlying proxy connection type is HTTP.
|
||||||
HTTPHostKey = "HttpHost"
|
HTTPHostKey = "HttpHost"
|
||||||
// HTTPRequestBodyHintKey is used in ConnectRequest metadata to indicate if the request has body
|
|
||||||
HTTPRequestBodyHintKey = "HttpReqBodyHint"
|
|
||||||
|
|
||||||
QUICMetadataFlowID = "FlowID"
|
QUICMetadataFlowID = "FlowID"
|
||||||
// emperically this capacity has been working well
|
// emperically this capacity has been working well
|
||||||
demuxChanCapacity = 16
|
demuxChanCapacity = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestBodyHint uint64
|
|
||||||
|
|
||||||
const (
|
|
||||||
RequestBodyHintMissing RequestBodyHint = iota
|
|
||||||
RequestBodyHintEmpty
|
|
||||||
RequestBodyHintHasData
|
|
||||||
)
|
|
||||||
|
|
||||||
func (rbh RequestBodyHint) String() string {
|
|
||||||
return [...]string{"missing", "empty", "data"}[rbh]
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
portForConnIndex = make(map[uint8]int, 0)
|
portForConnIndex = make(map[uint8]int, 0)
|
||||||
portMapMutex sync.Mutex
|
portMapMutex sync.Mutex
|
||||||
|
@ -500,6 +486,7 @@ func buildHTTPRequest(
|
||||||
dest := connectRequest.Dest
|
dest := connectRequest.Dest
|
||||||
method := metadata[HTTPMethodKey]
|
method := metadata[HTTPMethodKey]
|
||||||
host := metadata[HTTPHostKey]
|
host := metadata[HTTPHostKey]
|
||||||
|
isWebsocket := connectRequest.Type == pogs.ConnectionTypeWebsocket
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, method, dest, body)
|
req, err := http.NewRequestWithContext(ctx, method, dest, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -524,8 +511,13 @@ func buildHTTPRequest(
|
||||||
return nil, fmt.Errorf("Error setting content-length: %w", err)
|
return nil, fmt.Errorf("Error setting content-length: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if shouldSetRequestBodyToEmpty(connectRequest, metadata, req) {
|
// Go's client defaults to chunked encoding after a 200ms delay if the following cases are true:
|
||||||
log.Debug().Str("host", req.Host).Str("method", req.Method).Msg("Set request to have no body")
|
// * the request body blocks
|
||||||
|
// * the content length is not set (or set to -1)
|
||||||
|
// * the method doesn't usually have a body (GET, HEAD, DELETE, ...)
|
||||||
|
// * there is no transfer-encoding=chunked already set.
|
||||||
|
// So, if transfer cannot be chunked and content length is 0, we dont set a request body.
|
||||||
|
if !isWebsocket && !isTransferEncodingChunked(req) && req.ContentLength == 0 {
|
||||||
req.Body = http.NoBody
|
req.Body = http.NoBody
|
||||||
}
|
}
|
||||||
stripWebsocketUpgradeHeader(req)
|
stripWebsocketUpgradeHeader(req)
|
||||||
|
@ -550,35 +542,6 @@ func isTransferEncodingChunked(req *http.Request) bool {
|
||||||
return strings.Contains(strings.ToLower(transferEncodingVal), "chunked")
|
return strings.Contains(strings.ToLower(transferEncodingVal), "chunked")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Borrowed from https://github.com/golang/go/blob/go1.22.6/src/net/http/request.go#L1541
|
|
||||||
func requestMethodUsuallyLacksBody(req *http.Request) bool {
|
|
||||||
switch strings.ToUpper(req.Method) {
|
|
||||||
case "GET", "HEAD", "DELETE", "OPTIONS", "PROPFIND", "SEARCH":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldSetRequestBodyToEmpty(connectRequest *pogs.ConnectRequest, metadata map[string]string, req *http.Request) bool {
|
|
||||||
switch metadata[HTTPRequestBodyHintKey] {
|
|
||||||
case RequestBodyHintEmpty.String():
|
|
||||||
return true
|
|
||||||
case RequestBodyHintHasData.String():
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
isWebsocket := connectRequest.Type == pogs.ConnectionTypeWebsocket
|
|
||||||
// Go's client defaults to chunked encoding after a 200ms delay if the following cases are true:
|
|
||||||
// * the request body blocks
|
|
||||||
// * the content length is not set (or set to -1)
|
|
||||||
// * the method doesn't usually have a body (GET, HEAD, DELETE, ...)
|
|
||||||
// * there is no transfer-encoding=chunked already set.
|
|
||||||
// So, if transfer cannot be chunked and content length is 0, we dont set a request body.
|
|
||||||
// Reference: https://github.com/golang/go/blob/go1.22.2/src/net/http/transfer.go#L192-L206
|
|
||||||
return !isWebsocket && requestMethodUsuallyLacksBody(req) && !isTransferEncodingChunked(req) && req.ContentLength == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// A helper struct that guarantees a call to close only affects read side, but not write side.
|
// A helper struct that guarantees a call to close only affects read side, but not write side.
|
||||||
type nopCloserReadWriter struct {
|
type nopCloserReadWriter struct {
|
||||||
io.ReadWriteCloser
|
io.ReadWriteCloser
|
||||||
|
|
|
@ -486,125 +486,6 @@ func TestBuildHTTPRequest(t *testing.T) {
|
||||||
},
|
},
|
||||||
body: io.NopCloser(&bytes.Buffer{}),
|
body: io.NopCloser(&bytes.Buffer{}),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "if edge sends the body is empty hint, set body to empty",
|
|
||||||
connectRequest: &pogs.ConnectRequest{
|
|
||||||
Dest: "http://test.com",
|
|
||||||
Metadata: []pogs.Metadata{
|
|
||||||
{
|
|
||||||
Key: "HttpHeader:Another-Header",
|
|
||||||
Val: "Misc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "HttpHost",
|
|
||||||
Val: "cf.host",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "HttpMethod",
|
|
||||||
Val: "put",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: HTTPRequestBodyHintKey,
|
|
||||||
Val: RequestBodyHintEmpty.String(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
req: &http.Request{
|
|
||||||
Method: "put",
|
|
||||||
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",
|
|
||||||
Body: http.NoBody,
|
|
||||||
},
|
|
||||||
body: io.NopCloser(&bytes.Buffer{}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "if edge sends the body has data hint, don't set body to empty",
|
|
||||||
connectRequest: &pogs.ConnectRequest{
|
|
||||||
Dest: "http://test.com",
|
|
||||||
Metadata: []pogs.Metadata{
|
|
||||||
{
|
|
||||||
Key: "HttpHeader:Another-Header",
|
|
||||||
Val: "Misc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "HttpHost",
|
|
||||||
Val: "cf.host",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "HttpMethod",
|
|
||||||
Val: "put",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: HTTPRequestBodyHintKey,
|
|
||||||
Val: RequestBodyHintHasData.String(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
req: &http.Request{
|
|
||||||
Method: "put",
|
|
||||||
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",
|
|
||||||
Body: io.NopCloser(&bytes.Buffer{}),
|
|
||||||
},
|
|
||||||
body: io.NopCloser(&bytes.Buffer{}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "if the http method usually has body, don't set body to empty",
|
|
||||||
connectRequest: &pogs.ConnectRequest{
|
|
||||||
Dest: "http://test.com",
|
|
||||||
Metadata: []pogs.Metadata{
|
|
||||||
{
|
|
||||||
Key: "HttpHeader:Another-Header",
|
|
||||||
Val: "Misc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "HttpHost",
|
|
||||||
Val: "cf.host",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "HttpMethod",
|
|
||||||
Val: "post",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
req: &http.Request{
|
|
||||||
Method: "post",
|
|
||||||
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",
|
|
||||||
Body: io.NopCloser(&bytes.Buffer{}),
|
|
||||||
},
|
|
||||||
body: io.NopCloser(&bytes.Buffer{}),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
|
|
Loading…
Reference in New Issue