feat(api): add public status endpoints with version injection

Replace health_handler with status_handler providing public /status and
/about endpoints. Add build-time version injection via ldflags in
Makefile, and support --version/-v CLI flag.

- Add /status endpoint returning runtime status, uptime, and version
- Add /about endpoint with system metadata (name, description, repo)
- Configure VERSION variable with git describe fallback
- Update swagger docs and api.md for new public endpoints
- Remove deprecated /api/status/test endpoint
This commit is contained in:
zenfun
2025-12-27 13:24:13 +08:00
parent 3d39c591fd
commit 637bfa8210
8 changed files with 317 additions and 159 deletions

View File

@@ -1,37 +0,0 @@
package api
import (
"net/http"
"github.com/ez-api/ez-api/internal/service"
"github.com/gin-gonic/gin"
)
type HealthHandler struct {
svc *service.HealthCheckService
}
func NewHealthHandler(svc *service.HealthCheckService) *HealthHandler {
return &HealthHandler{svc: svc}
}
// TestDeps godoc
// @Summary Test dependency connectivity
// @Description Checks Redis/PostgreSQL connections and reports status
// @Tags system
// @Produce json
// @Success 200 {object} service.HealthStatus
// @Failure 503 {object} service.HealthStatus
// @Router /api/status/test [get]
func (h *HealthHandler) TestDeps(c *gin.Context) {
if h == nil || h.svc == nil {
c.JSON(http.StatusServiceUnavailable, gin.H{"status": "down"})
return
}
status := h.svc.Check(c.Request.Context())
httpStatus := http.StatusOK
if status.Status == "down" {
httpStatus = http.StatusServiceUnavailable
}
c.JSON(httpStatus, status)
}

View File

@@ -0,0 +1,81 @@
package api
import (
"net/http"
"time"
"github.com/ez-api/ez-api/internal/service"
"github.com/gin-gonic/gin"
)
// Version is set at build time using ldflags
// e.g., go build -ldflags "-X github.com/ez-api/ez-api/internal/api.Version=v1.0.0"
var Version = "v0.1.0-dev"
// startTime is used to calculate uptime
var startTime = time.Now()
// StatusHandler handles public status endpoints
type StatusHandler struct {
healthService *service.HealthCheckService
}
// NewStatusHandler creates a new StatusHandler
func NewStatusHandler(healthService *service.HealthCheckService) *StatusHandler {
return &StatusHandler{
healthService: healthService,
}
}
// StatusResponse represents the response for /status endpoint
type StatusResponse struct {
Status string `json:"status" example:"ok"`
Uptime string `json:"uptime" example:"72h30m15s"`
Version string `json:"version" example:"0.1.0"`
}
// AboutResponse represents the response for /about endpoint
type AboutResponse struct {
Name string `json:"name" example:"EZ-API Gateway"`
Version string `json:"version" example:"0.1.0"`
Description string `json:"description" example:"High-performance LLM API gateway"`
Repository string `json:"repository" example:"https://github.com/ez-api/ez-api"`
}
// Status godoc
// @Summary Get system status
// @Description Returns public runtime status information without sensitive data
// @Tags Public
// @Produce json
// @Success 200 {object} StatusResponse
// @Router /status [get]
func (h *StatusHandler) Status(c *gin.Context) {
// Check health status
health := h.healthService.Check(c.Request.Context())
resp := StatusResponse{
Status: health.Status,
Uptime: time.Since(startTime).Round(time.Second).String(),
Version: Version,
}
c.JSON(http.StatusOK, resp)
}
// About godoc
// @Summary Get system information
// @Description Returns system metadata for display on an about page
// @Tags Public
// @Produce json
// @Success 200 {object} AboutResponse
// @Router /about [get]
func (h *StatusHandler) About(c *gin.Context) {
resp := AboutResponse{
Name: "EZ-API Gateway",
Version: Version,
Description: "High-performance LLM API gateway",
Repository: "https://github.com/ez-api/ez-api",
}
c.JSON(http.StatusOK, resp)
}