package handler import ( "database/sql" "encoding/json" "fmt" "net/http" "net/url" "floorvisualizer/internal/middleware" "floorvisualizer/internal/openrouter" "floorvisualizer/internal/service" ) func NewProxyClient(proxyURLStr string) *http.Client { u, _ := url.Parse(proxyURLStr) if u == nil { return http.DefaultClient } return &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(u)}} } func RegisterAll(mux *http.ServeMux, client *openrouter.Client, db *sql.DB, authSvc *service.AuthService) { requireAuth := middleware.RequireAuth(authSvc) // Auth mux.HandleFunc("/auth/register", handleRegister(authSvc, db)) mux.HandleFunc("/auth/login", handleLogin(authSvc, db)) // User (protected) mux.HandleFunc("/user/me", requireAuth(handleMe(db))) mux.HandleFunc("/user/avatar", requireAuth(handleUploadAvatar(db))) mux.HandleFunc("/user/favorites", requireAuth(handleFavorites(db))) mux.HandleFunc("/user/favorites/", requireAuth(handleFavorites(db))) mux.HandleFunc("/user/projects", requireAuth(handleProjects(db))) mux.HandleFunc("/user/projects/", requireAuth(handleProjects(db))) mux.HandleFunc("/user/frequent-brands", requireAuth(handleFrequentBrands(db))) // Upload mux.HandleFunc("/healthz", handleHealthz) mux.HandleFunc("/upload", handleUpload) // Products mux.HandleFunc("/products", handleProducts(db)) mux.HandleFunc("/products/", handleProducts(db)) mux.HandleFunc("/product-options", handleProductOptions(db)) mux.HandleFunc("/filter-options", handleFilterOptions(db)) // Recommend mux.HandleFunc("/recommend/api", handleRecommend(db)) // Calculator mux.HandleFunc("/calculator/calc", handleCalc) // Floor AI mux.HandleFunc("/floor/generate", handleFloorGenerate(client, db)) mux.HandleFunc("/floor/status", handleFloorStatus) mux.HandleFunc("/floor/options", handleFloorOptions(db)) // Articles (recommend before /articles/ to avoid path conflict) mux.HandleFunc("/articles/recommend", handleArticleRecommend(db)) mux.HandleFunc("/articles", handleArticles(db)) mux.HandleFunc("/articles/", handleArticles(db)) // Static mux.Handle("/outputs/", http.StripPrefix("/outputs/", http.FileServer(http.Dir("./outputs")))) mux.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir("./uploads")))) mux.Handle("/knowledge_images/", http.StripPrefix("/knowledge_images/", http.FileServer(http.Dir("./knowledge_images")))) mux.Handle("/images/knowledge/", http.StripPrefix("/images/knowledge/", http.FileServer(http.Dir("./knowledge_images")))) } func writeJSON(w http.ResponseWriter, status int, v any) { w.Header().Set("Content-Type", "application/json") if status >= 400 { msg := "Unknown error" switch x := v.(type) { case string: msg = x case map[string]string: if e, ok := x["error"]; ok { msg = e } case map[string]any: if e, ok := x["error"]; ok { msg = fmt.Sprint(e) } } w.WriteHeader(status) json.NewEncoder(w).Encode(map[string]any{"code": status, "error": msg}) return } w.WriteHeader(status) json.NewEncoder(w).Encode(map[string]any{"code": status, "data": v}) } func writeErr(w http.ResponseWriter, status int, msg string) { writeJSON(w, status, msg) }