Ctrl K
ComunidadGuías…

server/cors.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package server

import (
	"net/http"
	"net/url"
	"strings"

	"github.com/usememos/memos/internal/httphandler"
	"github.com/usememos/memos/internal/profile"
)

func newCORSMiddleware(profile *profile.Profile, mux *http.ServeMux) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			h := w.Header()
			h.Add("Vary", "Origin")
			origin := r.Header.Get("Origin")
			preflight := r.Method == http.MethodOptions
			allowMethods := ""
			if preflight {
				handler, _ := mux.Handler(httphandler.RoutingRequest(r))
				if route, ok := handler.(interface{ AllowedMethods() string }); ok {
					allowMethods = route.AllowedMethods()
					if allowMethods != "" {
						h.Set("Allow", allowMethods)
					}
				}
			}
			if origin != "" && origin != "null" {
				h.Set("Access-Control-Allow-Origin", origin)
				// Cookie access remains restricted to trusted origins. Other origins
				// may use Authorization tokens, but must not read credentialed responses.
				if isAllowedCORSOrigin(profile, r.Host, origin) {
					h.Set("Access-Control-Allow-Credentials", "true")
				}
				if preflight {
					h.Add("Vary", "Access-Control-Request-Method")
					h.Add("Vary", "Access-Control-Request-Headers")
					if allowMethods == "" {
						allowMethods = "GET,HEAD,PUT,PATCH,POST,DELETE"
					}
					h.Set("Access-Control-Allow-Methods", allowMethods)
					if headers := r.Header.Get("Access-Control-Request-Headers"); headers != "" {
						h.Set("Access-Control-Allow-Headers", headers)
					}
				}
			}
			if preflight {
				w.WriteHeader(http.StatusNoContent)
				return
			}
			next.ServeHTTP(w, r)
		})
	}
}

func isAllowedCORSOrigin(profile *profile.Profile, requestHost, origin string) bool {
	originURL, err := url.Parse(origin)
	if err != nil || originURL.Scheme == "" || originURL.Host == "" {
		return false
	}

	if strings.EqualFold(originURL.Host, requestHost) {
		return true
	}

	if profile == nil || profile.InstanceURL == "" {
		return false
	}
	instanceURL, err := url.Parse(profile.InstanceURL)
	if err != nil || instanceURL.Scheme == "" || instanceURL.Host == "" {
		return false
	}
	return strings.EqualFold(originURL.Scheme, instanceURL.Scheme) && strings.EqualFold(originURL.Host, instanceURL.Host)
}