单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。 Co-authored-by: Cursor <cursoragent@cursor.com>
62 lines
1.9 KiB
Go
62 lines
1.9 KiB
Go
// v1handlers.go:HTTP 兜底面 /v1/search /v1/read(与 MCP tools/call 共用同一内核)。
|
||
package gateway
|
||
|
||
import (
|
||
"net/http"
|
||
|
||
"onesvm.com/onesvm/browser-server/internal/contract"
|
||
)
|
||
|
||
// handleV1Search POST /v1/search。
|
||
func (s *Server) handleV1Search(w http.ResponseWriter, r *http.Request, a *consumerAuth) {
|
||
var in contract.SearchInput
|
||
if err := jsonDecode(r, &in); err != nil {
|
||
s.writeErr(w, r, contract.CodeUnavailable, "请求体非法 JSON: "+err.Error(), http.StatusBadRequest, "", nil)
|
||
return
|
||
}
|
||
s.runAndRespond(w, r, a, runCtx{Intent: "search", Search: &in})
|
||
}
|
||
|
||
// handleV1Read POST /v1/read。
|
||
func (s *Server) handleV1Read(w http.ResponseWriter, r *http.Request, a *consumerAuth) {
|
||
var in contract.ReadInput
|
||
if err := jsonDecode(r, &in); err != nil {
|
||
s.writeErr(w, r, contract.CodeUnavailable, "请求体非法 JSON: "+err.Error(), http.StatusBadRequest, "", nil)
|
||
return
|
||
}
|
||
s.runAndRespond(w, r, a, runCtx{Intent: "read", Read: &in})
|
||
}
|
||
|
||
// runAndRespond 共用响应路径:管线 → 信封/错误输出。
|
||
func (s *Server) runAndRespond(w http.ResponseWriter, r *http.Request, a *consumerAuth, rc runCtx) {
|
||
rc.Auth = a
|
||
rc.W = w
|
||
rc.R = r
|
||
res := s.pipeline(rc)
|
||
switch {
|
||
case res.HTTPStatus != http.StatusOK && res.Body == nil:
|
||
// 前置错误(401/402/403/429/503)
|
||
w.Header().Set("Content-Type", "application/json")
|
||
if res.RetryAfterS != nil {
|
||
setRetryAfter(w, *res.RetryAfterS)
|
||
}
|
||
for k, v := range res.Headers {
|
||
w.Header().Set(k, v)
|
||
}
|
||
w.WriteHeader(res.HTTPStatus)
|
||
_, _ = w.Write(res.Body2)
|
||
case res.Body != nil:
|
||
// 完整信封(成功或 200 信封错误)
|
||
for k, v := range res.Headers {
|
||
w.Header().Set(k, v)
|
||
}
|
||
s.writeEnvelope(w, r, a, res.Body)
|
||
default:
|
||
s.writeErr(w, r, contract.CodeUpstream, "空管线结果", http.StatusInternalServerError, "", nil)
|
||
}
|
||
}
|
||
|
||
// setRetryAfter Retry-After 头。
|
||
func setRetryAfter(w http.ResponseWriter, secs int) {
|
||
w.Header().Set("Retry-After", itoa(secs))
|
||
}
|