From 164953d56d76a0cc33d6620263c780aed6fecfac Mon Sep 17 00:00:00 2001 From: mlogclub Date: Sat, 13 Jun 2026 09:59:21 +0800 Subject: [PATCH] feat: add health check endpoint and update Makefile for health URL --- Makefile | 2 +- internal/bootstrap/server.go | 2 ++ internal/bootstrap/server_route_test.go | 40 +++++++++++++++++++++++++ internal/handlers/api/health_handler.go | 15 ++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 internal/handlers/api/health_handler.go diff --git a/Makefile b/Makefile index 47a0e63..d47b753 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ GO ?= go PNPM ?= pnpm GOOS ?= $(shell $(GO) env GOOS) GOARCH ?= $(shell $(GO) env GOARCH) -DEV_SERVER_URL ?= http://127.0.0.1:8083 +DEV_SERVER_URL ?= http://127.0.0.1:8083/api/health LANCEDB_VERSION ?= v0.1.2 LANCEDB_DOWNLOAD_SCRIPT ?= https://raw.githubusercontent.com/lancedb/lancedb-go/main/scripts/download-artifacts.sh LANCEDB ?= 0 diff --git a/internal/bootstrap/server.go b/internal/bootstrap/server.go index 8dd5863..6a6c55e 100644 --- a/internal/bootstrap/server.go +++ b/internal/bootstrap/server.go @@ -8,6 +8,7 @@ import ( "agent-desk/internal/ai/mcps" _ "agent-desk/internal/ai/runtime" + "agent-desk/internal/handlers/api" "agent-desk/internal/middleware" "agent-desk/internal/pkg/config" "agent-desk/internal/pkg/ginx" @@ -154,6 +155,7 @@ func addRouter(app *gin.Engine) { app.Any("/api/mcp", gin.WrapH(mcps.NewHTTPHandler())) apiGroup := app.Group("/api") + apiGroup.GET("/health", api.Health) registerApiAuthRoutes(apiGroup.Group("/auth")) registerApiChannelRoutes(apiGroup.Group("/channel")) registerApiCustomerRoutes(apiGroup.Group("/customer")) diff --git a/internal/bootstrap/server_route_test.go b/internal/bootstrap/server_route_test.go index 42cd37c..241065a 100644 --- a/internal/bootstrap/server_route_test.go +++ b/internal/bootstrap/server_route_test.go @@ -32,6 +32,7 @@ func TestNewServerRegistersGinRoutes(t *testing.T) { expected := []string{ http.MethodPost + " /api/auth/login", + http.MethodGet + " /api/health", http.MethodGet + " /api/auth/oidc_login", http.MethodGet + " /api/auth/oidc_callback", http.MethodPost + " /api/auth/oidc_exchange", @@ -50,6 +51,45 @@ func TestNewServerRegistersGinRoutes(t *testing.T) { } } +func TestNewServerHealthEndpointIsPublic(t *testing.T) { + config.SetCurrent(&config.Config{ + Storage: config.StorageConfig{ + Local: config.LocalStorageConfig{ + Root: "storage", + BaseURL: "/storage", + }, + }, + }) + + app, err := NewServer() + if err != nil { + t.Fatalf("NewServer() error = %v", err) + } + + rec := httptest.NewRecorder() + app.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/health", nil)) + + if rec.Code != http.StatusOK { + t.Fatalf("status=%d want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String()) + } + + var body struct { + Success bool `json:"success"` + Data struct { + Status string `json:"status"` + } `json:"data"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatalf("unmarshal response: %v", err) + } + if !body.Success { + t.Fatalf("success=false, body=%s", rec.Body.String()) + } + if body.Data.Status != "ok" { + t.Fatalf("status=%q want ok", body.Data.Status) + } +} + func TestNewServerExposesPublicAuthOptions(t *testing.T) { config.SetCurrent(&config.Config{ Storage: config.StorageConfig{ diff --git a/internal/handlers/api/health_handler.go b/internal/handlers/api/health_handler.go new file mode 100644 index 0000000..094ab17 --- /dev/null +++ b/internal/handlers/api/health_handler.go @@ -0,0 +1,15 @@ +package api + +import ( + "agent-desk/internal/pkg/httpx" + + "github.com/gin-gonic/gin" +) + +type healthResponse struct { + Status string `json:"status"` +} + +func Health(ctx *gin.Context) { + httpx.WriteJSON(ctx, &healthResponse{Status: "ok"}) +}