diff --git a/middleware/cors.go b/middleware/cors.go index 6e194cc..7e0319c 100644 --- a/middleware/cors.go +++ b/middleware/cors.go @@ -49,7 +49,7 @@ type OriginValidator func(string) bool var ( defaultCorsOptionStatusCode = http.StatusOK defaultCorsMethods = []string{http.MethodHead, http.MethodGet, http.MethodPost} - defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"} + defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Type", "Content-Language", "Origin"} // (WebKit/Safari v9 sends the Origin header by default in AJAX requests). ) diff --git a/router.go b/router.go index a247006..5a4d546 100644 --- a/router.go +++ b/router.go @@ -14,9 +14,13 @@ type Router struct { } func NewRouter() *Router { - return &Router{ + r := &Router{ mux: http.NewServeMux(), } + + // catch all options + r.mux.Handle("OPTIONS /", optionsHandler{}) + return r } // Use will register middleware(s) with router stack @@ -27,48 +31,46 @@ func (r *Router) Use(h ...func(http.Handler) http.Handler) { r.middlewares = append(r.middlewares, h...) } -// Get method route -func (r *Router) Get(pattern string, h http.HandlerFunc) { +// GET method route +func (r *Router) GET(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodGet, pattern, h) } -// Head method route -func (r *Router) Head(pattern string, h http.HandlerFunc) { +// HEAD method route +func (r *Router) HEAD(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodHead, pattern, h) } -// Post method route -func (r *Router) Post(pattern string, h http.HandlerFunc) { +// POST method route +func (r *Router) POST(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodPost, pattern, h) } -// Put method route -func (r *Router) Put(pattern string, h http.HandlerFunc) { +// PUT method route +func (r *Router) PUT(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodPut, pattern, h) } -// Patch method route -func (r *Router) Patch(pattern string, h http.HandlerFunc) { +// PATCH method route +func (r *Router) PATCH(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodPatch, pattern, h) } -// Delete method route -func (r *Router) Delete(pattern string, h http.HandlerFunc) { +// DELETE method route +func (r *Router) DELETE(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodDelete, pattern, h) } -// Connect method route -func (r *Router) Connect(pattern string, h http.HandlerFunc) { +// CONNECT method route +func (r *Router) CONNECT(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodConnect, pattern, h) -} - -// Options method route -func (r *Router) Options(pattern string, h http.HandlerFunc) { +} // OPTIONS method route +func (r *Router) OPTIONS(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodOptions, pattern, h) } -// Trace method route -func (r *Router) Trace(pattern string, h http.HandlerFunc) { +// TRACE method route +func (r *Router) TRACE(pattern string, h http.HandlerFunc) { r.handlerFunc(http.MethodTrace, pattern, h) } diff --git a/router_options_handler.go b/router_options_handler.go new file mode 100644 index 0000000..223ecfa --- /dev/null +++ b/router_options_handler.go @@ -0,0 +1,21 @@ +package mux + +import ( + "io" + "net/http" +) + +type optionsHandler struct{} + +func (optionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Length", "0") + if r.ContentLength != 0 { + // Read up to 4KB of OPTIONS body (as mentioned in the + // spec as being reserved for future use), but anything + // over that is considered a waste of server resources + // (or an attack) and we abort and close the connection, + // courtesy of MaxBytesReader's EOF behavior. + mb := http.MaxBytesReader(w, r.Body, 4<<10) + io.Copy(io.Discard, mb) + } +}