diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 6394da3bb7cf60..b7f0614f6bb285 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -3434,6 +3434,42 @@ func TestOptions(t *testing.T) { } } +func TestOptionsHandler(t *testing.T) { + rc := make(chan *Request, 1) + + ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) { + t.Fatalf("Got unexpected request %v", r) + })) + ts.Config.OptionsHandler = HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Content-Length", "0") + rc <- r + }) + 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) + } + res, err := ReadResponse(bufio.NewReader(conn), &Request{Method: "OPTIONS"}) + if err != nil { + t.Fatal(err) + } + if res.StatusCode != 200 { + t.Errorf("Got non-200 response to OPTIONS *: %#v", res) + } + + if got := <-rc; got.Method != "OPTIONS" || got.RequestURI != "*" { + t.Errorf("Expected OPTIONS * request, got %v", got) + } +} + // 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 diff --git a/src/net/http/server.go b/src/net/http/server.go index e9b0b4d9bd9a28..bf963426811346 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2570,6 +2570,10 @@ type Server struct { Handler Handler // handler to invoke, http.DefaultServeMux if nil + // OptionsHandler handles "OPTIONS *" requests. + // If nil, server responds with 200 OK and Content-Length: 0. + OptionsHandler Handler + // 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 @@ -2897,7 +2901,10 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { handler = DefaultServeMux } if req.RequestURI == "*" && req.Method == "OPTIONS" { - handler = globalOptionsHandler{} + handler = sh.srv.OptionsHandler + if handler == nil { + handler = globalOptionsHandler{} + } } if req.URL != nil && strings.Contains(req.URL.RawQuery, ";") {