server: added DisableKeepalive option for disabling keep-alive connections

This commit is contained in:
Aliaksandr Valialkin
2016-03-31 10:05:31 +03:00
parent 9946a8145e
commit 7d29fb3b3d
2 changed files with 91 additions and 9 deletions
+20 -9
View File
@@ -152,6 +152,14 @@ type Server struct {
// DefaultConcurrency is used if not set.
Concurrency int
// Whether to disable keep-alive connections.
//
// The server will close all the incoming connections after sending
// the first response to client if this option is set to true.
//
// By default keep-alive connections are enabled.
DisableKeepalive bool
// Per-connection buffer size for requests' reading.
// This also limits the maximum header size.
//
@@ -1333,14 +1341,17 @@ func (s *Server) serveConn(c net.Conn) error {
connRequestNum := uint64(0)
ctx := s.acquireCtx(c)
var br *bufio.Reader
var bw *bufio.Writer
var err error
var connectionClose bool
var isHTTP11 bool
var timeoutResponse *Response
var hijackHandler HijackHandler
var (
br *bufio.Reader
bw *bufio.Writer
)
var (
err error
connectionClose bool
isHTTP11 bool
timeoutResponse *Response
hijackHandler HijackHandler
)
for {
ctx.id++
connRequestNum++
@@ -1422,7 +1433,7 @@ func (s *Server) serveConn(c net.Conn) error {
}
}
connectionClose = ctx.Request.Header.connectionCloseFast()
connectionClose = s.DisableKeepalive || ctx.Request.Header.connectionCloseFast()
isHTTP11 = ctx.Request.Header.IsHTTP11()
ctx.connRequestNum = connRequestNum
+71
View File
@@ -16,6 +16,77 @@ import (
"github.com/valyala/fasthttp/fasthttputil"
)
func TestServerDisableKeepalive(t *testing.T) {
s := &Server{
Handler: func(ctx *RequestCtx) {
ctx.WriteString("OK")
},
DisableKeepalive: true,
}
ln := fasthttputil.NewInmemoryListener()
serverCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverCh)
}()
clientCh := make(chan struct{})
go func() {
c, err := ln.Dial()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if _, err = c.Write([]byte("GET / HTTP/1.1\r\nHost: aa\r\n\r\n")); err != nil {
t.Fatalf("unexpected error: %s", err)
}
br := bufio.NewReader(c)
var resp Response
if err = resp.Read(br); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if resp.StatusCode() != StatusOK {
t.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode(), StatusOK)
}
if !resp.ConnectionClose() {
t.Fatalf("expecting 'Connection: close' response header")
}
if string(resp.Body()) != "OK" {
t.Fatalf("unexpected body: %q. Expecting %q", resp.Body(), "OK")
}
// make sure the connection is closed
data, err := ioutil.ReadAll(br)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if len(data) > 0 {
t.Fatalf("unexpected data read from the connection: %q. Expecting empty data", data)
}
close(clientCh)
}()
select {
case <-clientCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
func TestServerMaxConnsPerIPLimit(t *testing.T) {
s := &Server{
Handler: func(ctx *RequestCtx) {