onesvm-browser-server/server/cmd/browser-server/probe.go
chii eb972dfa93 feat: 落地 browser-server 控制面并打通 mgr1 海外订阅
单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 15:05:12 +08:00

51 lines
2.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// probe.go — serveHealth /healthz 已注册探测(V3 arch-review D-1 修复辅助)。
package main
import "net/http"
// muxPatternRegistered 探测 ServeMux 是否已注册某 pattern。
// ServeMux 无公开查询 API;Handler 面走一次探测请求即可判断。
// 返回 nil 表示未注册(可安全补挂),非 nil 表示已在路由表。
//
// 实现说明:Go 1.22+ ServeMux 用 Handler(r) 做匹配;若精确 pattern 已注册,
// Handler 返回的 p.pattern 等于查询串。此处用最朴素的方式:构造一个指向
// 目标 pattern 的请求,若 Handler 命中且非内置 404 处理器即视为已注册。
func muxPatternRegistered(mux *http.ServeMux, pattern string) http.Handler {
req, err := http.NewRequest(http.MethodGet, "http://probe.invalid"+pattern, nil)
if err != nil {
return nil // 构造失败按未注册处理(后续 HandleFunc 会 panic 暴露问题)
}
h, _ := mux.Handler(req)
// 内置 404(NotFoundHandler)意味着 pattern 未注册——ServeMux.Handler 对
// 完全未命中且无 "/" 兜底的请求返回 NotFoundHandler。
if h == nil {
return nil
}
if h == http.DefaultServeMux {
return nil
}
// 未注册时 ServeMux.Handler 返回 http.NotFoundHandler(包级单例)。
if _, ok := h.(http.Handler); ok {
// 判 404:包一层探测 recoder 看状态码不可行(Handler 只在 Serve 时执行),
// 改用类型特征:ServeMux 未命中返回的 handler 即 mux 自身的 notFoundHandler,
// 其与 http.NotFoundHandler() 每次为不同实例——因此不能靠指针比较。
// 简化判定:ServeMux.Handler 命中已注册 pattern 时返回该 pattern 的 handler;
// 未命中时返回的不是任何用户注册的 handler。此处采用行为探测:执行一次。
w := &probeRecorder{header: http.Header{}, status: 0}
h.ServeHTTP(w, req)
if w.status == http.StatusNotFound {
return nil
}
}
return h
}
// probeRecorder 探测用 ResponseWriter(不落网络)。
type probeRecorder struct {
header http.Header
status int
}
func (p *probeRecorder) Header() http.Header { return p.header }
func (p *probeRecorder) Write(b []byte) (int, error) { return len(b), nil }
func (p *probeRecorder) WriteHeader(code int) { p.status = code }