diff options
Diffstat (limited to 'vendor/go.mau.fi/util/exhttp')
-rw-r--r-- | vendor/go.mau.fi/util/exhttp/cors.go | 26 | ||||
-rw-r--r-- | vendor/go.mau.fi/util/exhttp/handleerrors.go | 58 | ||||
-rw-r--r-- | vendor/go.mau.fi/util/exhttp/json.go | 27 | ||||
-rw-r--r-- | vendor/go.mau.fi/util/exhttp/middleware.go | 24 |
4 files changed, 135 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/util/exhttp/cors.go b/vendor/go.mau.fi/util/exhttp/cors.go new file mode 100644 index 0000000..037be8d --- /dev/null +++ b/vendor/go.mau.fi/util/exhttp/cors.go @@ -0,0 +1,26 @@ +package exhttp + +import "net/http" + +func AddCORSHeaders(w http.ResponseWriter) { + // Recommended CORS headers can be found in https://spec.matrix.org/v1.3/client-server-api/#web-browser-clients + 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", "X-Requested-With, Content-Type, Authorization") + w.Header().Set("Content-Security-Policy", "sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';") + // Allow browsers to cache above for 1 day + w.Header().Set("Access-Control-Max-Age", "86400") +} + +// CORSMiddleware adds CORS headers to the response and handles OPTIONS +// requests by returning 200 OK immediately. +func CORSMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + AddCORSHeaders(w) + if r.Method == http.MethodOptions { + w.WriteHeader(http.StatusOK) + return + } + next.ServeHTTP(w, r) + }) +} diff --git a/vendor/go.mau.fi/util/exhttp/handleerrors.go b/vendor/go.mau.fi/util/exhttp/handleerrors.go new file mode 100644 index 0000000..d2d37b1 --- /dev/null +++ b/vendor/go.mau.fi/util/exhttp/handleerrors.go @@ -0,0 +1,58 @@ +package exhttp + +import "net/http" + +type ErrorBodyGenerators struct { + NotFound func() []byte + MethodNotAllowed func() []byte +} + +func HandleErrors(next http.Handler, gen ErrorBodyGenerators) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next.ServeHTTP(&bodyOverrider{ + ResponseWriter: w, + statusNotFoundBodyGenerator: gen.NotFound, + statusMethodNotAllowedBodyGenerator: gen.MethodNotAllowed, + }, r) + }) +} + +type bodyOverrider struct { + http.ResponseWriter + + code int + override bool + + statusNotFoundBodyGenerator func() []byte + statusMethodNotAllowedBodyGenerator func() []byte +} + +var _ http.ResponseWriter = (*bodyOverrider)(nil) + +func (b *bodyOverrider) WriteHeader(code int) { + if b.Header().Get("Content-Type") == "text/plain; charset=utf-8" { + b.Header().Set("Content-Type", "application/json") + + b.override = true + } + + b.code = code + b.ResponseWriter.WriteHeader(code) +} + +func (b *bodyOverrider) Write(body []byte) (int, error) { + if b.override { + switch b.code { + case http.StatusNotFound: + if b.statusNotFoundBodyGenerator != nil { + body = b.statusNotFoundBodyGenerator() + } + case http.StatusMethodNotAllowed: + if b.statusMethodNotAllowedBodyGenerator != nil { + body = b.statusMethodNotAllowedBodyGenerator() + } + } + } + + return b.ResponseWriter.Write(body) +} diff --git a/vendor/go.mau.fi/util/exhttp/json.go b/vendor/go.mau.fi/util/exhttp/json.go new file mode 100644 index 0000000..48c8349 --- /dev/null +++ b/vendor/go.mau.fi/util/exhttp/json.go @@ -0,0 +1,27 @@ +package exhttp + +import ( + "encoding/json" + "net/http" +) + +func WriteJSONResponse(w http.ResponseWriter, httpStatusCode int, jsonData any) { + AddCORSHeaders(w) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpStatusCode) + _ = json.NewEncoder(w).Encode(jsonData) +} + +func WriteJSONData(w http.ResponseWriter, httpStatusCode int, data []byte) { + AddCORSHeaders(w) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpStatusCode) + _, _ = w.Write(data) +} + +func WriteEmptyJSONResponse(w http.ResponseWriter, httpStatusCode int) { + AddCORSHeaders(w) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpStatusCode) + _, _ = w.Write([]byte("{}")) +} diff --git a/vendor/go.mau.fi/util/exhttp/middleware.go b/vendor/go.mau.fi/util/exhttp/middleware.go new file mode 100644 index 0000000..733d348 --- /dev/null +++ b/vendor/go.mau.fi/util/exhttp/middleware.go @@ -0,0 +1,24 @@ +package exhttp + +import "net/http" + +// Middleware represents a middleware that can be applied to an [http.Handler]. +type Middleware func(http.Handler) http.Handler + +// ApplyMiddleware applies the provided [Middleware] functions to the given +// router. The middlewares will be applied in the order they are provided. +func ApplyMiddleware(router http.Handler, middlewares ...Middleware) http.Handler { + // Apply middlewares in reverse order because the first middleware provided + // needs to be the outermost one. + for i := len(middlewares) - 1; i >= 0; i-- { + router = middlewares[i](router) + } + return router +} + +// StripPrefix is a wrapper for [http.StripPrefix] is compatible with the middleware pattern. +func StripPrefix(prefix string) Middleware { + return func(next http.Handler) http.Handler { + return http.StripPrefix(prefix, next) + } +} |