package httpapp import ( "net/http" "strings" "gitea.avt.data-center.id/othman.suseno/atlas/internal/errors" ) // httpsEnforcementMiddleware enforces HTTPS connections func (a *App) httpsEnforcementMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Skip HTTPS enforcement for health checks and localhost if a.isPublicEndpoint(r.URL.Path, r.Method) || isLocalhost(r) { next.ServeHTTP(w, r) return } // If TLS is enabled, enforce HTTPS if a.tlsConfig != nil && a.tlsConfig.Enabled { // Check if request is already over HTTPS if r.TLS != nil { next.ServeHTTP(w, r) return } // Check X-Forwarded-Proto header (for reverse proxies) if r.Header.Get("X-Forwarded-Proto") == "https" { next.ServeHTTP(w, r) return } // Redirect HTTP to HTTPS httpsURL := "https://" + r.Host + r.URL.RequestURI() http.Redirect(w, r, httpsURL, http.StatusMovedPermanently) return } next.ServeHTTP(w, r) }) } // isLocalhost checks if the request is from localhost func isLocalhost(r *http.Request) bool { host := r.Host if strings.Contains(host, ":") { host = strings.Split(host, ":")[0] } return host == "localhost" || host == "127.0.0.1" || host == "::1" } // requireHTTPSMiddleware requires HTTPS for all requests (strict mode) func (a *App) requireHTTPSMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Skip for health checks if a.isPublicEndpoint(r.URL.Path, r.Method) { next.ServeHTTP(w, r) return } // If TLS is enabled, require HTTPS if a.tlsConfig != nil && a.tlsConfig.Enabled { // Check if request is over HTTPS if r.TLS == nil && r.Header.Get("X-Forwarded-Proto") != "https" { writeError(w, errors.NewAPIError( errors.ErrCodeForbidden, "HTTPS required", http.StatusForbidden, ).WithDetails("this endpoint requires HTTPS")) return } } next.ServeHTTP(w, r) }) }