mirror of
https://github.com/octoleo/syncthing.git
synced 2024-09-19 21:29:01 +00:00
Merge branch 'pr/2735'
* pr/2735: Add a CORS handler to deal with preflight OPTIONS requests
This commit is contained in:
commit
0ce45c20b8
@ -240,6 +240,9 @@ func (s *apiService) Serve() {
|
|||||||
// protected, other requests will grant cookies.
|
// protected, other requests will grant cookies.
|
||||||
handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg.APIKey(), mux)
|
handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg.APIKey(), mux)
|
||||||
|
|
||||||
|
// Add the CORS handling
|
||||||
|
handler = corsMiddleware(handler)
|
||||||
|
|
||||||
// Add our version and ID as a header to responses
|
// Add our version and ID as a header to responses
|
||||||
handler = withDetailsMiddleware(s.id, handler)
|
handler = withDetailsMiddleware(s.id, handler)
|
||||||
|
|
||||||
@ -375,6 +378,37 @@ func debugMiddleware(h http.Handler) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func corsMiddleware(next http.Handler) http.Handler {
|
||||||
|
// Handle CORS headers and CORS OPTIONS request.
|
||||||
|
// CORS OPTIONS request are typically sent by browser during AJAX preflight
|
||||||
|
// when the browser initiate a POST request.
|
||||||
|
// See https://www.w3.org/TR/cors/ for details.
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Add a generous access-control-allow-origin header since we may be
|
||||||
|
// redirecting REST requests over protocols
|
||||||
|
w.Header().Add("Access-Control-Allow-Origin", "*")
|
||||||
|
|
||||||
|
// Process OPTIONS requests
|
||||||
|
if r.Method == "OPTIONS" {
|
||||||
|
// Only GET/POST Methods are supported
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
|
||||||
|
// Only this custom header can be set
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", "X-API-Key")
|
||||||
|
// The request is meant to be cached 10 minutes
|
||||||
|
w.Header().Set("Access-Control-Max-Age", "600")
|
||||||
|
|
||||||
|
// Indicate that no content will be returned
|
||||||
|
w.WriteHeader(204)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// For everything else, pass to the next handler
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func metricsMiddleware(h http.Handler) http.Handler {
|
func metricsMiddleware(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
t := metrics.GetOrRegisterTimer(r.URL.Path, nil)
|
t := metrics.GetOrRegisterTimer(r.URL.Path, nil)
|
||||||
@ -386,10 +420,6 @@ func metricsMiddleware(h http.Handler) http.Handler {
|
|||||||
|
|
||||||
func redirectToHTTPSMiddleware(h http.Handler) http.Handler {
|
func redirectToHTTPSMiddleware(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// Add a generous access-control-allow-origin header since we may be
|
|
||||||
// redirecting REST requests over protocols
|
|
||||||
w.Header().Add("Access-Control-Allow-Origin", "*")
|
|
||||||
|
|
||||||
if r.TLS == nil {
|
if r.TLS == nil {
|
||||||
// Redirect HTTP requests to HTTPS
|
// Redirect HTTP requests to HTTPS
|
||||||
r.URL.Host = r.Host
|
r.URL.Host = r.Host
|
||||||
|
@ -172,6 +172,24 @@ func TestGetJSON(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOptions(t *testing.T) {
|
||||||
|
p := startInstance(t, 2)
|
||||||
|
defer checkedStop(t, p)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("OPTIONS", "http://127.0.0.1:8082/rest/system/error/clear", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
res.Body.Close()
|
||||||
|
if res.StatusCode != 204 {
|
||||||
|
t.Fatalf("Status %d != 204 for OPTIONS", res.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPOSTWithoutCSRF(t *testing.T) {
|
func TestPOSTWithoutCSRF(t *testing.T) {
|
||||||
p := startInstance(t, 2)
|
p := startInstance(t, 2)
|
||||||
defer checkedStop(t, p)
|
defer checkedStop(t, p)
|
||||||
|
Loading…
Reference in New Issue
Block a user