package openapi import ( "fmt" "html/template" "net/http" "strings" "github.com/gorilla/mux" ) // UIType represents the type of OpenAPI UI to serve type UIType string const ( // SwaggerUI is the most popular OpenAPI UI SwaggerUI UIType = "swagger-ui" // RapiDoc is a modern, customizable OpenAPI UI RapiDoc UIType = "rapidoc" // Redoc is a clean, responsive OpenAPI UI Redoc UIType = "redoc" // Scalar is a modern and sleek OpenAPI UI Scalar UIType = "scalar" ) // UIConfig holds configuration for the OpenAPI UI handler type UIConfig struct { // UIType specifies which UI framework to use (default: SwaggerUI) UIType UIType // SpecURL is the URL to the OpenAPI spec JSON (default: "/openapi") SpecURL string // Title is the page title (default: "API Documentation") Title string // FaviconURL is the URL to the favicon (optional) FaviconURL string // CustomCSS allows injecting custom CSS (optional) CustomCSS string // Theme for the UI (light/dark, depends on UI type) Theme string } // UIHandler creates an HTTP handler that serves an OpenAPI UI func UIHandler(config UIConfig) http.HandlerFunc { // Set defaults if config.UIType == "" { config.UIType = SwaggerUI } if config.SpecURL == "" { config.SpecURL = "/openapi" } if config.Title == "" { config.Title = "API Documentation" } if config.Theme == "" { config.Theme = "light" } return func(w http.ResponseWriter, r *http.Request) { var htmlContent string var err error switch config.UIType { case SwaggerUI: htmlContent, err = generateSwaggerUI(config) case RapiDoc: htmlContent, err = generateRapiDoc(config) case Redoc: htmlContent, err = generateRedoc(config) case Scalar: htmlContent, err = generateScalar(config) default: http.Error(w, "Unsupported UI type", http.StatusBadRequest) return } if err != nil { http.Error(w, fmt.Sprintf("Failed to generate UI: %v", err), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusOK) _, err = w.Write([]byte(htmlContent)) if err != nil { http.Error(w, fmt.Sprintf("Failed to write response: %v", err), http.StatusInternalServerError) return } } } // templateData wraps UIConfig to properly handle CSS in templates type templateData struct { UIConfig SafeCustomCSS template.CSS } // generateSwaggerUI generates the HTML for Swagger UI func generateSwaggerUI(config UIConfig) (string, error) { tmpl := `