| @ -0,0 +1,63 @@ | |||||
| package middleware | |||||
| import ( | |||||
| "io" | |||||
| "net/http" | |||||
| "net/http/httptest" | |||||
| "strings" | |||||
| "github.com/zenazn/goji/web" | |||||
| ) | |||||
| // Automatically return an appropriate "Allow" header when the request method is | |||||
| // OPTIONS and the request would have otherwise been 404'd. | |||||
| func AutomaticOptions(c *web.C, h http.Handler) http.Handler { | |||||
| fn := func(w http.ResponseWriter, r *http.Request) { | |||||
| // This will probably slow down OPTIONS calls a bunch, but it | |||||
| // probably won't happen too much, and it'll just be hitting the | |||||
| // 404 route anyways. | |||||
| var fw *httptest.ResponseRecorder | |||||
| pw := w | |||||
| if strings.ToUpper(r.Method) == "OPTIONS" { | |||||
| fw = httptest.NewRecorder() | |||||
| pw = fw | |||||
| } | |||||
| h.ServeHTTP(pw, r) | |||||
| if fw == nil { | |||||
| return | |||||
| } | |||||
| for k, v := range fw.Header() { | |||||
| w.Header()[k] = v | |||||
| } | |||||
| methods := getValidMethods(*c) | |||||
| if fw.Code == http.StatusNotFound && methods != nil { | |||||
| w.Header().Set("Allow", strings.Join(methods, ", ")) | |||||
| w.WriteHeader(http.StatusOK) | |||||
| } else { | |||||
| w.WriteHeader(fw.Code) | |||||
| io.Copy(w, fw.Body) | |||||
| } | |||||
| } | |||||
| return http.HandlerFunc(fn) | |||||
| } | |||||
| func getValidMethods(c web.C) []string { | |||||
| if c.Env == nil { | |||||
| return nil | |||||
| } | |||||
| v, ok := c.Env["goji.web.validMethods"] | |||||
| if !ok { | |||||
| return nil | |||||
| } | |||||
| if methods, ok := v.([]string); ok { | |||||
| return methods | |||||
| } else { | |||||
| return nil | |||||
| } | |||||
| } | |||||