Do not read response body for HEAD requests
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
This commit is contained in:
parent
ad99c5bbea
commit
0528c054a6
3 changed files with 46 additions and 6 deletions
|
@ -20,6 +20,7 @@ import (
|
||||||
// rwWithUpgrade contains a ResponseWriter and an upgradeHandler,
|
// rwWithUpgrade contains a ResponseWriter and an upgradeHandler,
|
||||||
// used to upgrade the connection (e.g. Websockets).
|
// used to upgrade the connection (e.g. Websockets).
|
||||||
type rwWithUpgrade struct {
|
type rwWithUpgrade struct {
|
||||||
|
ReqMethod string
|
||||||
RW http.ResponseWriter
|
RW http.ResponseWriter
|
||||||
Upgrade upgradeHandler
|
Upgrade upgradeHandler
|
||||||
}
|
}
|
||||||
|
@ -211,6 +212,10 @@ func (c *conn) handleResponse(r rwWithUpgrade) error {
|
||||||
|
|
||||||
r.RW.WriteHeader(res.StatusCode())
|
r.RW.WriteHeader(res.StatusCode())
|
||||||
|
|
||||||
|
if noResponseBodyExpected(r.ReqMethod) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if res.Header.ContentLength() == 0 {
|
if res.Header.ContentLength() == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -444,8 +449,8 @@ func (c *connPool) askForNewConn(errCh chan<- error) {
|
||||||
c.releaseConn(newConn)
|
c.releaseConn(newConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBodyAllowedForStatus reports whether a given response status code
|
// isBodyAllowedForStatus reports whether a given response status code permits a body.
|
||||||
// permits a body. See RFC 7230, section 3.3.
|
// See RFC 7230, section 3.3.
|
||||||
// From https://github.com/golang/go/blame/master/src/net/http/transfer.go#L459
|
// From https://github.com/golang/go/blame/master/src/net/http/transfer.go#L459
|
||||||
func isBodyAllowedForStatus(status int) bool {
|
func isBodyAllowedForStatus(status int) bool {
|
||||||
switch {
|
switch {
|
||||||
|
@ -458,3 +463,9 @@ func isBodyAllowedForStatus(status int) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// noResponseBodyExpected reports whether a given request method permits a body.
|
||||||
|
// From https://github.com/golang/go/blame/master/src/net/http/transfer.go#L250
|
||||||
|
func noResponseBodyExpected(requestMethod string) bool {
|
||||||
|
return requestMethod == "HEAD"
|
||||||
|
}
|
||||||
|
|
|
@ -284,6 +284,7 @@ func (p *ReverseProxy) roundTrip(rw http.ResponseWriter, req *http.Request, outR
|
||||||
|
|
||||||
// Sending the responseWriter unlocks the connection readLoop, to handle the response.
|
// Sending the responseWriter unlocks the connection readLoop, to handle the response.
|
||||||
co.RWCh <- rwWithUpgrade{
|
co.RWCh <- rwWithUpgrade{
|
||||||
|
ReqMethod: req.Method,
|
||||||
RW: rw,
|
RW: rw,
|
||||||
Upgrade: upgradeResponseHandler(req.Context(), reqUpType),
|
Upgrade: upgradeResponseHandler(req.Context(), reqUpType),
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,6 +278,34 @@ func TestPreservePath(t *testing.T) {
|
||||||
assert.Equal(t, http.StatusOK, res.Code)
|
assert.Equal(t, http.StatusOK, res.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHeadRequest(t *testing.T) {
|
||||||
|
var callCount int
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
callCount++
|
||||||
|
|
||||||
|
assert.Equal(t, http.MethodHead, req.Method)
|
||||||
|
|
||||||
|
rw.Header().Set("Content-Length", "42")
|
||||||
|
}))
|
||||||
|
t.Cleanup(server.Close)
|
||||||
|
|
||||||
|
builder := NewProxyBuilder(&transportManagerMock{}, static.FastProxyConfig{})
|
||||||
|
|
||||||
|
serverURL, err := url.JoinPath(server.URL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
proxyHandler, err := builder.Build("", testhelpers.MustParseURL(serverURL), true, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodHead, "/", http.NoBody)
|
||||||
|
res := httptest.NewRecorder()
|
||||||
|
|
||||||
|
proxyHandler.ServeHTTP(res, req)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, callCount)
|
||||||
|
assert.Equal(t, http.StatusOK, res.Code)
|
||||||
|
}
|
||||||
|
|
||||||
func newCertificate(t *testing.T, domain string) *tls.Certificate {
|
func newCertificate(t *testing.T, domain string) *tls.Certificate {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue