mirror of
https://github.com/soypat/lneto.git
synced 2026-08-18 13:44:02 +00:00
httphi.Handle rejects unsupported protocols
This commit is contained in:
@@ -262,6 +262,58 @@ func TestHandleMalformedRequest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A request-line naming a version this package does not speak must be answered
|
||||
// 505 without reaching a handler, RFC 9112 2.6. The third token is not
|
||||
// validated by the parser, so anything that is not HTTP/1.0 or HTTP/1.1 lands
|
||||
// here: bogus versions, non-HTTP tokens, and the tail of a request-target that
|
||||
// contained a space and got split across the URI/protocol boundary.
|
||||
func TestHandleUnsupportedProtocol(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
request string
|
||||
}{
|
||||
{name: "future major", request: "GET / HTTP/6.9\r\nHost: h\r\n\r\n"},
|
||||
{name: "future major keepalive", request: "GET / HTTP/6.9\r\nHost: h\r\nConnection: keep-alive\r\n\r\n"},
|
||||
{name: "http2", request: "GET / HTTP/2.0\r\nHost: h\r\n\r\n"},
|
||||
{name: "long minor", request: "GET / HTTP/1.10\r\nHost: h\r\n\r\n"},
|
||||
{name: "lowercase", request: "GET / http/1.1\r\nHost: h\r\n\r\n"},
|
||||
{name: "not http", request: "GET / BANANA\r\nHost: h\r\n\r\n"},
|
||||
{name: "space in target", request: "GET /a b HTTP/1.1\r\nHost: h\r\n\r\n"},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var handled bool
|
||||
var sm MuxSlice
|
||||
sm.Handle("/", func(ex *Exchange) { handled = true })
|
||||
sm.Handle("/a", func(ex *Exchange) { handled = true })
|
||||
conn := newConn(test.request)
|
||||
conn.Hangup()
|
||||
exch := newExchange(t, conn, ExchangeConfig{RawBuf: make([]byte, 2*1024), RequestBufferLim: 1024})
|
||||
if err := Handle(exch, &sm, nopBackoff); err == nil {
|
||||
t.Error("want error on unsupported protocol, got nil")
|
||||
}
|
||||
if handled {
|
||||
t.Error("handler must not run on unsupported protocol")
|
||||
}
|
||||
const want = "HTTP/1.1 505 HTTP Version Not Supported\r\n\r\n"
|
||||
if got := conn.ViewWritten(); got != want {
|
||||
t.Errorf("want %q, got %q", want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP/1.0 predates HTTP/1.1 but is still served: only the connection is not
|
||||
// kept alive. It must not be swept up by the 505 gate.
|
||||
func TestHandleHTTP10Served(t *testing.T) {
|
||||
var sm MuxSlice
|
||||
sm.Handle("/", func(ex *Exchange) { ex.WriteHeader(200) })
|
||||
conn := serve(t, "GET / HTTP/1.0\r\nHost: h\r\n\r\n", &sm)
|
||||
const want = "HTTP/1.1 200 OK\r\n\r\n"
|
||||
if got := conn.ViewWritten(); got != want {
|
||||
t.Errorf("want %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// No registered handler must yield 404, not an empty response.
|
||||
func TestHandleNoHandler(t *testing.T) {
|
||||
var sm MuxSlice
|
||||
|
||||
+7
-3
@@ -52,11 +52,15 @@ func Handle(exch *Exchange, mux Mux, backoff lneto.BackoffStrategy) error {
|
||||
exch.respRemains = reqhdr.BufferReceived() - parsed
|
||||
exch.respHeaderOff = uint16(parsed)
|
||||
exch.respHeaderLen = 0
|
||||
if len(reqhdr.Protocol()) == 0 {
|
||||
// Request line with no HTTP version is a HTTP/0.9 simple-request, which
|
||||
// httpraw tolerates. It is not a valid HTTP/1.1 request-line, RFC 9112 3.
|
||||
proto := b2s(reqhdr.Protocol())
|
||||
if len(proto) == 0 {
|
||||
// HTTP/0.9 not tolerated RFC 9112 3.
|
||||
exch.WriteHeader(int(StatusBadRequest))
|
||||
return errNoRequestProto
|
||||
} else if proto != "HTTP/1.1" && proto != "HTTP/1.0" {
|
||||
// RFC 9112 2.6.
|
||||
exch.WriteHeader(int(StatusHTTPVersionNotSupported))
|
||||
return errBadRequestProto
|
||||
}
|
||||
// Mux on the request path: the query string is the handler's business.
|
||||
path := reqhdr.RequestPath()
|
||||
|
||||
@@ -20,7 +20,8 @@ import (
|
||||
const reconfigureWait = 10 * time.Millisecond
|
||||
|
||||
var (
|
||||
errNoRequestProto = errors.New("httphi: request line with no HTTP version")
|
||||
errNoRequestProto = errors.New("httphi: request line with no HTTP version")
|
||||
errBadRequestProto = errors.New("httphi: unsupported HTTP version in request line")
|
||||
errBusyExchanges = errors.New("httphi: exchanges still serving, cannot reuse their buffers")
|
||||
errRouterTornDown = errors.New("httphi: router torn down, configure it before serving")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user