102 lines
2.8 KiB
Go
102 lines
2.8 KiB
Go
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)
|
||
|
|
}
|