Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: reset request after reset user values on keep-alive connections #1162

Merged
merged 2 commits into from Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions server.go
Expand Up @@ -2118,6 +2118,7 @@ func (s *Server) serveConn(c net.Conn) (err error) {
br, err = acquireByteReader(&ctx)
}

reqReset = false
ctx.Request.isTLS = isTLS
ctx.Response.Header.noDefaultContentType = s.NoDefaultContentType
ctx.Response.Header.noDefaultDate = s.NoDefaultDate
Expand Down Expand Up @@ -2302,8 +2303,6 @@ func (s *Server) serveConn(c net.Conn) (err error) {
if !ctx.IsGet() && ctx.IsHead() {
ctx.Response.SkipBody = true
}
reqReset = true
ctx.Request.Reset()

hijackHandler = ctx.hijackHandler
ctx.hijackHandler = nil
Expand Down Expand Up @@ -2404,6 +2403,9 @@ func (s *Server) serveConn(c net.Conn) (err error) {
s.setState(c, StateIdle)
ctx.userValues.Reset()

reqReset = true
ctx.Request.Reset()

if atomic.LoadInt32(&s.stop) == 1 {
err = nil
break
Expand Down
46 changes: 46 additions & 0 deletions server_test.go
Expand Up @@ -25,6 +25,15 @@ import (
// Make sure RequestCtx implements context.Context
var _ context.Context = &RequestCtx{}

type closerWithRequestCtx struct {
ctx *RequestCtx
closeFunc func(ctx *RequestCtx) error
}

func (c *closerWithRequestCtx) Close() error {
return c.closeFunc(c.ctx)
}

func TestServerCRNLAfterPost_Pipeline(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -2032,6 +2041,43 @@ func TestRequestCtxWriteString(t *testing.T) {
}
}

func TestServeConnKeepRequestValuesUntilResetUserValues(t *testing.T) {
t.Parallel()

reqStr := "POST /foo HTTP/1.0\r\nHost: google.com\r\nContent-Type: application/octet-stream\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n"

rw := &readWriter{}
rw.r.WriteString(reqStr)

var resultReqStr string

ch := make(chan struct{})
go func() {
err := ServeConn(rw, func(ctx *RequestCtx) {
ctx.SetUserValue("myKey", &closerWithRequestCtx{
ctx: ctx,
closeFunc: func(closerCtx *RequestCtx) error {
resultReqStr = closerCtx.Request.String()
return nil
}})
})
if err != nil {
t.Errorf("unexpected error in ServeConn: %s", err)
}
close(ch)
}()

select {
case <-ch:
case <-time.After(time.Second):
t.Fatal("timeout")
}

if resultReqStr != reqStr {
t.Errorf("Request == %s, want %s", resultReqStr, reqStr)
}
}

func TestServeConnNonHTTP11KeepAlive(t *testing.T) {
t.Parallel()

Expand Down