mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-14 15:56:44 +03:00
Set ConnectionClose for non-http/1.1 requests/responses. Do not support Connection: keep-alive for http/1.0 intentionally, since it will complicate the code without measurable benefits
This commit is contained in:
@@ -781,11 +781,15 @@ func (h *ResponseHeader) parseFirstLine(buf []byte) (b []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// skip protocol
|
||||
// parse protocol
|
||||
n := bytes.IndexByte(b, ' ')
|
||||
if n < 0 {
|
||||
return nil, fmt.Errorf("cannot find whitespace in the first line of response %q", buf)
|
||||
}
|
||||
if !bytes.Equal(b[:n], strHTTP11) {
|
||||
// Non-http/1.1 response. Close connection after it.
|
||||
h.ConnectionClose = true
|
||||
}
|
||||
b = b[n+1:]
|
||||
|
||||
// parse status code
|
||||
@@ -819,9 +823,14 @@ func (h *RequestHeader) parseFirstLine(buf []byte) (b []byte, err error) {
|
||||
// parse requestURI
|
||||
n = bytes.LastIndexByte(b, ' ')
|
||||
if n < 0 {
|
||||
// no http protocol found. Close connection after the request.
|
||||
h.ConnectionClose = true
|
||||
n = len(b)
|
||||
} else if n == 0 {
|
||||
return nil, fmt.Errorf("RequestURI cannot be empty in %q", buf)
|
||||
} else if !bytes.Equal(b[n+1:], strHTTP11) {
|
||||
// non-http/1.1 protocol. Close connection after the request.
|
||||
h.ConnectionClose = true
|
||||
}
|
||||
h.RequestURI = append(h.RequestURI[:0], b[:n]...)
|
||||
|
||||
|
||||
+55
-2
@@ -10,6 +10,56 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResponseHeaderHTTPVer(t *testing.T) {
|
||||
// non-http/1.1
|
||||
testResponseHeaderHTTPVer(t, "HTTP/1.0 200 OK\r\nContent-Type: aaa\r\nContent-Length: 123\r\n\r\n", true)
|
||||
testResponseHeaderHTTPVer(t, "HTTP/0.9 200 OK\r\nContent-Type: aaa\r\nContent-Length: 123\r\n\r\n", true)
|
||||
testResponseHeaderHTTPVer(t, "foobar 200 OK\r\nContent-Type: aaa\r\nContent-Length: 123\r\n\r\n", true)
|
||||
|
||||
// http/1.1
|
||||
testResponseHeaderHTTPVer(t, "HTTP/1.1 200 OK\r\nContent-Type: aaa\r\nContent-Length: 123\r\n\r\n", false)
|
||||
}
|
||||
|
||||
func TestRequestHeaderHTTPVer(t *testing.T) {
|
||||
// non-http/1.1
|
||||
testRequestHeaderHTTPVer(t, "GET / HTTP/1.0\r\nHost: aa.com\r\n\r\n", true)
|
||||
testRequestHeaderHTTPVer(t, "GET / HTTP/0.9\r\nHost: aa.com\r\n\r\n", true)
|
||||
testRequestHeaderHTTPVer(t, "GET / foobar\r\nHost: aa.com\r\n\r\n", true)
|
||||
|
||||
// empty http version
|
||||
testRequestHeaderHTTPVer(t, "GET /\r\nHost: aaa.com\r\n\r\n", true)
|
||||
testRequestHeaderHTTPVer(t, "GET / \r\nHost: aaa.com\r\n\r\n", true)
|
||||
|
||||
// http/1.1
|
||||
testRequestHeaderHTTPVer(t, "GET / HTTP/1.1\r\nHost: a.com\r\n\r\n", false)
|
||||
}
|
||||
|
||||
func testResponseHeaderHTTPVer(t *testing.T, s string, connectionClose bool) {
|
||||
var h ResponseHeader
|
||||
|
||||
r := bytes.NewBufferString(s)
|
||||
br := bufio.NewReader(r)
|
||||
if err := h.Read(br); err != nil {
|
||||
t.Fatalf("unexpected error: %s. response=%q", err, s)
|
||||
}
|
||||
if h.ConnectionClose != connectionClose {
|
||||
t.Fatalf("unexpected connectionClose %v. Expecting %v. response=%q", h.ConnectionClose, connectionClose, s)
|
||||
}
|
||||
}
|
||||
|
||||
func testRequestHeaderHTTPVer(t *testing.T, s string, connectionClose bool) {
|
||||
var h RequestHeader
|
||||
|
||||
r := bytes.NewBufferString(s)
|
||||
br := bufio.NewReader(r)
|
||||
if err := h.Read(br); err != nil {
|
||||
t.Fatalf("unexpected error: %s. request=%q", err, s)
|
||||
}
|
||||
if h.ConnectionClose != connectionClose {
|
||||
t.Fatalf("unexpected connectionClose %v. Expecting %v. request=%q", h.ConnectionClose, connectionClose, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResponseHeaderCopyTo(t *testing.T) {
|
||||
var h ResponseHeader
|
||||
|
||||
@@ -719,13 +769,16 @@ func TestRequestHeaderReadSuccess(t *testing.T) {
|
||||
// ancient http protocol
|
||||
testRequestHeaderReadSuccess(t, h, "GET /bar HTTP/1.0\r\nHost: gole\r\n\r\npppp",
|
||||
0, "/bar", "gole", "", "", "pppp")
|
||||
if h.ConnectionClose {
|
||||
t.Fatalf("unexpected connection: close header")
|
||||
if !h.ConnectionClose {
|
||||
t.Fatalf("expecting connectionClose for ancient http protocol")
|
||||
}
|
||||
|
||||
// complex headers with body
|
||||
testRequestHeaderReadSuccess(t, h, "GET /aabar HTTP/1.1\r\nAAA: bbb\r\nHost: ole.com\r\nAA: bb\r\n\r\nzzz",
|
||||
0, "/aabar", "ole.com", "", "", "zzz")
|
||||
if h.ConnectionClose {
|
||||
t.Fatalf("unexpected connection: close")
|
||||
}
|
||||
|
||||
// lf instead of crlf
|
||||
testRequestHeaderReadSuccess(t, h, "GET /foo/bar HTTP/1.1\nHost: google.com\n\n",
|
||||
|
||||
Reference in New Issue
Block a user