新增 HTTP/HTTPS 与 SQL Server 支持,完善账号映射、凭据生命周期、角色和 API Token 隔离。实现健康检查、告警、配置导入导出、模板与历史差异,并补充管理界面、回归测试和运维文档。
61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
func source(r *http.Request) string {
|
|
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
|
if err != nil {
|
|
return r.RemoteAddr
|
|
}
|
|
return host
|
|
}
|
|
|
|
func decode(w http.ResponseWriter, r *http.Request, v any) bool {
|
|
return decodeLimit(w, r, v, 1<<20)
|
|
}
|
|
|
|
func decodeLimit(w http.ResponseWriter, r *http.Request, v any, limit int64) bool {
|
|
r.Body = http.MaxBytesReader(w, r.Body, limit)
|
|
d := json.NewDecoder(r.Body)
|
|
d.DisallowUnknownFields()
|
|
if err := d.Decode(v); err != nil {
|
|
fail(w, 400, "invalid JSON body")
|
|
return false
|
|
}
|
|
var extra any
|
|
if err := d.Decode(&extra); err != io.EOF {
|
|
fail(w, 400, "expected one JSON object")
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func respond(w http.ResponseWriter, status int, v any) {
|
|
if _, restricted := w.(tokenResponseWriter); restricted {
|
|
raw, err := json.Marshal(v)
|
|
if err != nil {
|
|
http.Error(w, "response encoding failed", 500)
|
|
return
|
|
}
|
|
var value any
|
|
if err = json.Unmarshal(raw, &value); err != nil {
|
|
http.Error(w, "response encoding failed", 500)
|
|
return
|
|
}
|
|
redactTokenResponse(value)
|
|
v = value
|
|
}
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
w.WriteHeader(status)
|
|
_ = json.NewEncoder(w).Encode(v)
|
|
}
|
|
|
|
func fail(w http.ResponseWriter, status int, message string) {
|
|
respond(w, status, map[string]string{"error": message})
|
|
}
|