package api import ( "fmt" "log" "net/http" "strings" "go.temporal.io/sdk/client" "github.com/rockliang/poimen/workflows/pkg/db" ) // Server handles HTTP routing for workflow APIs type Server struct { api *WorkflowAPI logger *log.Logger } // NewServer creates new HTTP server with database connection func NewServer(database *db.DB, temporalClient client.Client, logger *log.Logger) *Server { return &Server{ api: NewWorkflowAPI(database, temporalClient, logger), logger: logger, } } // ServeHTTP dispatches HTTP requests to appropriate handler func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Enable CORS w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") if r.Method == http.MethodOptions { w.WriteHeader(http.StatusOK) return } path := r.URL.Path method := r.Method s.logger.Printf("%s %s", method, path) // Route requests switch { // Workflow endpoints case path == "/workflows" && method == http.MethodPost: s.api.CreateWorkflow(w, r) case path == "/workflows" && method == http.MethodGet: s.api.ListWorkflows(w, r) case strings.HasPrefix(path, "/workflows/") && method == http.MethodGet: id := strings.TrimPrefix(path, "/workflows/") // Exclude special paths if !strings.Contains(id, "/") { s.api.GetWorkflow(w, r, id) } else if strings.HasSuffix(id, "/executions") { // GET /workflows/{id}/executions workflowID := strings.TrimSuffix(id, "/executions") s.api.ListExecutions(w, r, workflowID) } case strings.HasPrefix(path, "/workflows/") && method == http.MethodPut: id := extractID(path, "/workflows/") s.api.UpdateWorkflow(w, r, id) case strings.HasPrefix(path, "/workflows/") && method == http.MethodDelete: id := extractID(path, "/workflows/") s.api.DeleteWorkflow(w, r, id) // Execute workflow case strings.HasSuffix(path, "/execute") && method == http.MethodPost: // POST /workflows/{id}/execute parts := strings.Split(path, "/") if len(parts) >= 4 && parts[1] == "workflows" && parts[3] == "execute" { s.api.ExecuteWorkflow(w, r, parts[2]) } // Execution endpoints case strings.HasPrefix(path, "/executions/") && method == http.MethodGet: id := extractID(path, "/executions/") s.api.GetExecution(w, r, id) default: http.Error(w, "Not found", http.StatusNotFound) } } // extractID extracts resource ID from path func extractID(path, prefix string) string { id := strings.TrimPrefix(path, prefix) if idx := strings.Index(id, "/"); idx != -1 { return id[:idx] } return id } // Start starts the HTTP server func (s *Server) Start(port int) error { addr := fmt.Sprintf(":%d", port) s.logger.Printf("Starting API server on %s", addr) return http.ListenAndServe(addr, s) }