feat(server): API relay gateway backend M0-M4

Gin + GORM + pure-Go SQLite. Users/auth (JWT), API key management with
quotas, proxy gateway with weighted channel failover and health checks,
usage/billing ledger, cross-protocol conversion (Anthropic Messages /
OpenAI Chat Completions / OpenAI Responses), and channel/model admin API.
Channels declare native API formats and auto-convert the rest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Sakurasan
2026-08-15 21:05:02 +08:00
co-authored by Claude Sonnet 5
parent b0c7439c01
commit d0e31b198f
45 changed files with 6222 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
package httpx
import (
"net/http"
"github.com/gin-gonic/gin"
)
// APIError is the standard error body for the management API.
type APIError struct {
Code int `json:"code"`
Message string `json:"message"`
}
// OK writes a JSON success response.
func OK(c *gin.Context, data any) {
c.JSON(http.StatusOK, gin.H{"code": 0, "data": data})
}
// Created writes a 201 response.
func Created(c *gin.Context, data any) {
c.JSON(http.StatusCreated, gin.H{"code": 0, "data": data})
}
// Fail writes an error response with the given status.
func Fail(c *gin.Context, status int, message string) {
c.AbortWithStatusJSON(status, gin.H{"code": status, "message": message})
}
// FailWithCode writes an error with a custom business code.
func FailWithCode(c *gin.Context, status, code int, message string) {
c.AbortWithStatusJSON(status, gin.H{"code": code, "message": message})
}
// Bind parses the JSON body and aborts with 400 on failure.
func Bind(c *gin.Context, dst any) bool {
if err := c.ShouldBindJSON(dst); err != nil {
Fail(c, http.StatusBadRequest, "invalid request body: "+err.Error())
return false
}
return true
}