package openai import ( "net/http" "strings" "time" ) func (s *Server) routes() *http.ServeMux { mux := http.NewServeMux() mux.HandleFunc("/healthz", s.handleHealthz) mux.HandleFunc("/v1/models", s.withAuth(s.handleModels)) mux.HandleFunc("/v1/chat/completions", s.withAuth(s.handleChatCompletions)) mux.HandleFunc("/v1/responses", s.withAuth(s.handleResponses)) mux.HandleFunc("/api/", s.withAuth(s.handleOllamaAPI)) return mux } func (s *Server) withAuth(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { principal, ok := principalFromRequest(r, s.cfg) if !ok { w.Header().Set("WWW-Authenticate", `Bearer realm="iop-openai"`) writeError(w, http.StatusUnauthorized, "unauthorized", "unauthorized") return } next(w, r.WithContext(withPrincipal(r.Context(), principal))) } } func (s *Server) handleHealthz(w http.ResponseWriter, _ *http.Request) { writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } func (s *Server) handleModels(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { writeError(w, http.StatusMethodNotAllowed, "method_not_allowed", "method not allowed") return } var modelIDs []string modelCatalog := s.modelCatalogSnapshot() if len(modelCatalog) > 0 { // Provider pool catalog takes priority over legacy model_routes. for _, entry := range modelCatalog { if id := strings.TrimSpace(entry.ID); id != "" { modelIDs = append(modelIDs, id) } } } else if len(s.cfg.ModelRoutes) > 0 { for _, route := range s.cfg.ModelRoutes { id := strings.TrimSpace(route.Model) if id != "" && route.Target != "" { modelIDs = append(modelIDs, id) } } } else { modelIDs = s.cfg.Models if len(modelIDs) == 0 && s.cfg.Target != "" { modelIDs = []string{s.cfg.Target} } } data := make([]openAIModel, 0, len(modelIDs)) for _, model := range modelIDs { model = strings.TrimSpace(model) if model == "" { continue } data = append(data, openAIModel{ ID: model, Object: "model", Created: time.Now().Unix(), OwnedBy: "iop", }) } writeJSON(w, http.StatusOK, openAIModelsResponse{Object: "list", Data: data}) }