From 7d67791d176f1177e13665683ba05c993337de6e Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 1 Dec 2017 11:37:06 +0000 Subject: [PATCH] Add CORS headers to all responses including errors While util.MakeJSONAPI handles adding CORS headers and OPTIONS requests, that only gets hit for known APIs. This means that clients get CORS errors for unkown APIs, rather than seeing the 404, which causes them to retry. --- .../cmd/dendrite-client-api-server/main.go | 2 +- .../cmd/dendrite-media-api-server/main.go | 2 +- .../cmd/dendrite-monolith-server/main.go | 2 +- .../dendrite-public-rooms-api-server/main.go | 2 +- .../cmd/dendrite-sync-api-server/main.go | 2 +- .../matrix-org/dendrite/common/httpapi.go | 20 +++++++++++++++++-- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-client-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-client-api-server/main.go index 929fd3b5a..8794107fc 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-client-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-client-api-server/main.go @@ -121,7 +121,7 @@ func main() { queryAPI, aliasAPI, accountDB, deviceDB, federation, keyRing, userUpdateProducer, syncProducer, ) - common.SetupHTTPAPI(http.DefaultServeMux, api) + common.SetupHTTPAPI(http.DefaultServeMux, common.WrapHandlerInCORS(api)) log.Fatal(http.ListenAndServe(string(cfg.Listen.ClientAPI), nil)) } diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-media-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-media-api-server/main.go index 5092f4278..bc16dee79 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-media-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-media-api-server/main.go @@ -70,7 +70,7 @@ func main() { api := mux.NewRouter() routing.Setup(api, cfg, db, deviceDB, client) - common.SetupHTTPAPI(http.DefaultServeMux, api) + common.SetupHTTPAPI(http.DefaultServeMux, common.WrapHandlerInCORS(api)) log.Fatal(http.ListenAndServe(string(cfg.Listen.MediaAPI), nil)) } diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go index 05fc4252b..9ecfd60ab 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go @@ -103,7 +103,7 @@ func main() { // Expose the matrix APIs directly rather than putting them under a /api path. go func() { log.Info("Listening on ", *httpBindAddr) - log.Fatal(http.ListenAndServe(*httpBindAddr, m.api)) + log.Fatal(http.ListenAndServe(*httpBindAddr, common.WrapHandlerInCORS(m.api))) }() // Handle HTTPS if certificate and key are provided go func() { diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-public-rooms-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-public-rooms-api-server/main.go index 448ede7d3..24aae0dac 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-public-rooms-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-public-rooms-api-server/main.go @@ -85,7 +85,7 @@ func main() { api := mux.NewRouter() routing.Setup(api, deviceDB, db) - common.SetupHTTPAPI(http.DefaultServeMux, api) + common.SetupHTTPAPI(http.DefaultServeMux, common.WrapHandlerInCORS(api)) log.Fatal(http.ListenAndServe(string(cfg.Listen.PublicRoomsAPI), nil)) } diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go index e7f83a60d..16ae228b2 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-sync-api-server/main.go @@ -105,7 +105,7 @@ func main() { api := mux.NewRouter() routing.Setup(api, sync.NewRequestPool(db, n, adb), db, deviceDB) - common.SetupHTTPAPI(http.DefaultServeMux, api) + common.SetupHTTPAPI(http.DefaultServeMux, common.WrapHandlerInCORS(api)) log.Fatal(http.ListenAndServe(string(cfg.Listen.SyncAPI), nil)) } diff --git a/src/github.com/matrix-org/dendrite/common/httpapi.go b/src/github.com/matrix-org/dendrite/common/httpapi.go index 76182bf0f..5a6fcef0a 100644 --- a/src/github.com/matrix-org/dendrite/common/httpapi.go +++ b/src/github.com/matrix-org/dendrite/common/httpapi.go @@ -4,7 +4,6 @@ import ( "net/http" "time" - "github.com/gorilla/mux" "github.com/matrix-org/dendrite/clientapi/auth" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/gomatrixserverlib" @@ -87,8 +86,25 @@ func MakeFedAPI( // SetupHTTPAPI registers an HTTP API mux under /api and sets up a metrics // listener. -func SetupHTTPAPI(servMux *http.ServeMux, apiMux *mux.Router) { +func SetupHTTPAPI(servMux *http.ServeMux, apiMux http.Handler) { // This is deprecated. servMux.Handle("/metrics", prometheus.Handler()) // nolint: megacheck, staticcheck servMux.Handle("/api/", http.StripPrefix("/api", apiMux)) } + +// WrapHandlerInCORS adds CORS headers to all responses, including all error +// responses. +// Handles OPTIONS requests directly. +func WrapHandlerInCORS(h http.Handler) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") + + if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" { + w.WriteHeader(http.StatusOK) + } else { + h.ServeHTTP(w, r) + } + }) +}