net/http: add Server.DisableGeneralOptionsHandler for custom handling of OPTIONS *

Fixes #41773
This commit is contained in:
Alexander Yastrebov 2021-10-16 17:49:39 +02:00
parent 03fb5d7574
commit 57d1ee249d
3 changed files with 37 additions and 1 deletions

1
api/next/41773.txt Normal file
View file

@ -0,0 +1 @@
pkg net/http, type Server struct, DisableGeneralOptionsHandler bool #41773

View file

@ -3492,6 +3492,37 @@ func TestOptions(t *testing.T) {
}
}
func TestOptionsHandler(t *testing.T) {
rc := make(chan *Request, 1)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
rc <- r
}))
ts.Config.DisableGeneralOptionsHandler = true
ts.Start()
defer ts.Close()
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
if err != nil {
t.Fatal(err)
}
defer conn.Close()
_, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
if err != nil {
t.Fatal(err)
}
select {
case got := <-rc:
if got.Method != "OPTIONS" || got.RequestURI != "*" {
t.Errorf("Expected OPTIONS * request, got %v", got)
}
case <-time.After(5 * time.Second):
t.Error("timeout")
}
}
// Tests regarding the ordering of Write, WriteHeader, Header, and
// Flush calls. In Go 1.0, rw.WriteHeader immediately flushed the
// (*response).header to the wire. In Go 1.1, the actual wire flush is

View file

@ -2584,6 +2584,10 @@ type Server struct {
Handler Handler // handler to invoke, http.DefaultServeMux if nil
// DisableGeneralOptionsHandler, if true, passes "OPTIONS *" requests to the Handler,
// otherwise responds with 200 OK and Content-Length: 0.
DisableGeneralOptionsHandler bool
// TLSConfig optionally provides a TLS configuration for use
// by ServeTLS and ListenAndServeTLS. Note that this value is
// cloned by ServeTLS and ListenAndServeTLS, so it's not
@ -2916,7 +2920,7 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
if !sh.srv.DisableGeneralOptionsHandler && req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}