package middleware import ( "net/http" "strings" "time" "mirror-proxy/internal/admin" ) // CORS 跨域中间件 func CORS(next http.Handler) http.Handler { 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, HEAD, PATCH") w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, Origin, X-Requested-With") w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Type, X-Docker-Token") w.Header().Set("Access-Control-Max-Age", "86400") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) } // Logger 日志中间件 func Logger(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() wrapped := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK} next.ServeHTTP(wrapped, r) // 简单日志输出 _ = start }) } type responseWriter struct { http.ResponseWriter statusCode int } func (rw *responseWriter) WriteHeader(code int) { rw.statusCode = code rw.ResponseWriter.WriteHeader(code) } // SessionAuth 基于 Cookie Session 的认证中间件 func SessionAuth(sessions *admin.SessionStore, loginPath string) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("session") if err != nil { unauthorized(w, r, loginPath) return } _, ok := sessions.Get(cookie.Value) if !ok { unauthorized(w, r, loginPath) return } next.ServeHTTP(w, r) }) } } func unauthorized(w http.ResponseWriter, r *http.Request, loginPath string) { accept := r.Header.Get("Accept") isAPI := strings.Contains(r.URL.Path, "/api/") || strings.Contains(accept, "application/json") if isAPI { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(`{"error":"unauthorized"}`)) return } http.Redirect(w, r, loginPath, http.StatusFound) } // StripPrefix 安全地移除路径前缀 func StripPrefix(prefix string, h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { p := strings.TrimPrefix(r.URL.Path, prefix) if p == r.URL.Path { http.NotFound(w, r) return } r.URL.Path = p h.ServeHTTP(w, r) }) }