c26b06f1cc
Go 控制面(SQLite + REST API)嵌入 Mihomo 数据面,Vue 3 多语言 Web 管理台。 含订阅/节点/规则/出站/监控/日志、OpenAPI、API Key、Gitea Actions CI 与开源文档; CI 使用 ubuntu-latest runner,Go/Docker 步骤走国内镜像与 shell,避免 GitHub 下载超时。 Co-authored-by: Cursor <cursoragent@cursor.com>
52 lines
1.1 KiB
Go
52 lines
1.1 KiB
Go
package api
|
|
|
|
import (
|
|
_ "embed"
|
|
"encoding/json"
|
|
"net/http"
|
|
"sync"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
//go:embed openapi/spec.yaml
|
|
var openAPISpecYAML []byte
|
|
|
|
//go:embed openapi/docs.html
|
|
var openAPIDocsHTML []byte
|
|
|
|
var (
|
|
openAPIJSONOnce sync.Once
|
|
openAPIJSON []byte
|
|
openAPIJSONErr error
|
|
)
|
|
|
|
func loadOpenAPIJSON() {
|
|
var doc any
|
|
if err := yaml.Unmarshal(openAPISpecYAML, &doc); err != nil {
|
|
openAPIJSONErr = err
|
|
return
|
|
}
|
|
openAPIJSON, openAPIJSONErr = json.Marshal(doc)
|
|
}
|
|
|
|
func (s *Server) serveOpenAPIJSON(c *gin.Context) {
|
|
openAPIJSONOnce.Do(loadOpenAPIJSON)
|
|
if openAPIJSONErr != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": openAPIJSONErr.Error()})
|
|
return
|
|
}
|
|
c.Header("Cache-Control", "public, max-age=300")
|
|
c.Data(http.StatusOK, "application/json; charset=utf-8", openAPIJSON)
|
|
}
|
|
|
|
func (s *Server) serveOpenAPIYAML(c *gin.Context) {
|
|
c.Header("Cache-Control", "public, max-age=300")
|
|
c.Data(http.StatusOK, "application/yaml; charset=utf-8", openAPISpecYAML)
|
|
}
|
|
|
|
func (s *Server) serveOpenAPIDocs(c *gin.Context) {
|
|
c.Data(http.StatusOK, "text/html; charset=utf-8", openAPIDocsHTML)
|
|
}
|