service/document.go

146 lines
2.8 KiB
Go
Raw Permalink Normal View History

package service
import (
"apigo.cc/go/cast"
_ "embed"
"encoding/json"
"reflect"
)
// Api 接口文档信息
type Api struct {
Type string
Path string
AuthLevel int
Method string
In any
Out any
Memo string
Host string
}
// MakeDocument 生成文档数据
func MakeDocument() []Api {
2026-06-04 18:16:46 +08:00
return DefaultServer.MakeDocument()
}
func (ws *webServer) MakeDocument() []Api {
out := make([]Api, 0)
// 1. Rewrite & Proxy
2026-06-04 18:16:46 +08:00
ws.hostPoliciesLock.RLock()
for host, rewrites := range ws.hostRewrites {
for _, a := range rewrites {
out = append(out, Api{
Type: "Rewrite",
Host: host,
Path: a.fromPath + " -> " + a.toPath,
})
}
}
2026-06-04 18:16:46 +08:00
for host, proxies := range ws.hostProxies {
for _, a := range proxies {
out = append(out, Api{
Type: "Proxy",
Host: host,
Path: a.fromPath + " -> " + a.toApp + ":" + a.toPath,
})
}
}
2026-06-04 18:16:46 +08:00
ws.hostPoliciesLock.RUnlock()
// 2. Web Services
2026-06-04 18:16:46 +08:00
ws.webServicesLock.RLock()
for _, a := range ws.webServicesList {
if a.options.NoDoc {
continue
}
api := Api{
Type: "Web",
Path: a.path,
AuthLevel: a.authLevel,
Method: a.method,
Memo: a.memo,
Host: a.host,
}
if a.inType != nil {
api.In = getType(a.inType)
}
if a.funcType.NumOut() > 0 {
api.Out = getType(a.funcType.Out(0))
}
out = append(out, api)
}
2026-06-04 18:16:46 +08:00
ws.webServicesLock.RUnlock()
// 4. WebSocket Services
2026-06-04 18:16:46 +08:00
ws.websocketServicesLock.RLock()
for _, wsc := range ws.websocketServicesList {
api := Api{
Type: "WebSocket",
2026-06-04 18:16:46 +08:00
Path: wsc.path,
AuthLevel: wsc.authLevel,
Memo: wsc.memo,
Host: wsc.host,
}
2026-06-04 18:16:46 +08:00
if wsc.funcType != nil && wsc.funcType.NumIn() > 0 {
// Find struct in
2026-06-04 18:16:46 +08:00
for i := 0; i < wsc.funcType.NumIn(); i++ {
t := wsc.funcType.In(i)
if t.Kind() == reflect.Struct {
api.In = getType(t)
break
}
}
}
out = append(out, api)
}
2026-06-04 18:16:46 +08:00
ws.websocketServicesLock.RUnlock()
return out
}
// MakeJsonDocument 生成 JSON 格式文档
func MakeJsonDocument() string {
apis := MakeDocument()
data, _ := json.MarshalIndent(map[string]any{
"api": apis,
}, "", "\t")
return string(data)
}
func getType(t reflect.Type) any {
if t == nil {
return ""
}
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
switch t.Kind() {
case reflect.Struct:
outs := make(map[string]any)
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Anonymous {
if subMap, ok := getType(f.Type).(map[string]any); ok {
for k, v := range subMap {
outs[k] = v
}
}
} else {
outs[cast.GetLowerName(f.Name)] = getType(f.Type)
}
}
return outs
case reflect.Map:
return map[string]any{t.Key().String(): getType(t.Elem())}
case reflect.Slice:
return []any{getType(t.Elem())}
case reflect.Interface:
return "Any"
default:
return t.String()
}
}