fix version 1

This commit is contained in:
2026-09-22 21:15:34 +08:00
parent 9f86366638
commit d63d7e8b3a
277 changed files with 9959 additions and 1514 deletions

View File

@@ -35,12 +35,24 @@ func New(key string, expireSeconds int64, anonymous []string) (*Server, error) {
engine.Use(gin.Logger(), gin.Recovery())
return &Server{
GRPC: grpcServer,
Gateway: gwRuntime.NewServeMux(),
Gateway: gwRuntime.NewServeMux(gwRuntime.WithRoutingErrorHandler(routeMissHandler)),
HTTP: engine,
auth: auth,
}, nil
}
// routeMissHandler 是 grpc-gateway 的路由错误处理器:只有"路由未命中"才会被标记,
// 随后仍按默认行为写出错误体。业务 handler 返回的 NotFound 走的是 errorHandler
// 不会被标记,因而其响应能原样透出而不会被 Gin 的纯文本 404 覆盖。
func routeMissHandler(ctx context.Context, mux *gwRuntime.ServeMux, marshaler gwRuntime.Marshaler, w http.ResponseWriter, r *http.Request, httpStatus int) {
if httpStatus == http.StatusNotFound {
if recorder, ok := w.(routingMissRecorder); ok {
recorder.markRoutingMiss()
}
}
gwRuntime.DefaultRoutingErrorHandler(ctx, mux, marshaler, w, r, httpStatus)
}
func (s *Server) Start(grpcAddr, httpAddr string) error {
grpcListener, err := net.Listen("tcp", grpcAddr)
if err != nil {
@@ -60,18 +72,9 @@ func (s *Server) Start(grpcAddr, httpAddr string) error {
}
s.HTTP.POST("/rpc/:module/:service/:method", s.dynamic.handle)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
recorder := newBufferedResponse()
s.Gateway.ServeHTTP(recorder, r)
if recorder.status != http.StatusNotFound {
recorder.flush(w)
return
}
s.HTTP.ServeHTTP(w, r)
})
s.http = &http.Server{
Addr: httpAddr,
Handler: s.auth.httpMiddleware(handler),
Handler: s.auth.httpMiddleware(s.handler()),
ReadHeaderTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20,
@@ -89,6 +92,21 @@ func (s *Server) Start(grpcAddr, httpAddr string) error {
return serveErr
}
// handler 先让 grpc-gateway 处理请求,仅当网关确实未命中路由时才回退到 Gin
// (动态 RPC 与原生的 /rest 路由都注册在 Gin 上)。业务返回的 404/NotFound
// 属于网关的正常响应,必须原样透出。
func (s *Server) handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
recorder := newBufferedResponse()
s.Gateway.ServeHTTP(recorder, r)
if !recorder.routingMiss {
recorder.flush(w)
return
}
s.HTTP.ServeHTTP(w, r)
})
}
func (s *Server) Stop(ctx context.Context) error {
stopped := make(chan struct{})
go func() {
@@ -109,10 +127,17 @@ func (s *Server) Stop(ctx context.Context) error {
return s.http.Shutdown(ctx)
}
// routingMissRecorder 由 bufferedResponse 实现,用于区分"网关未命中路由"与业务 NotFound。
type routingMissRecorder interface {
markRoutingMiss()
}
type bufferedResponse struct {
header http.Header
body bytes.Buffer
status int
// routingMiss 表示该 404 来自 grpc-gateway 的路由错误处理,而非业务响应。
routingMiss bool
}
func newBufferedResponse() *bufferedResponse {
@@ -122,6 +147,7 @@ func newBufferedResponse() *bufferedResponse {
func (r *bufferedResponse) Header() http.Header { return r.header }
func (r *bufferedResponse) WriteHeader(status int) { r.status = status }
func (r *bufferedResponse) Write(data []byte) (int, error) { return r.body.Write(data) }
func (r *bufferedResponse) markRoutingMiss() { r.routingMiss = true }
func (r *bufferedResponse) flush(w http.ResponseWriter) {
for key, values := range r.header {
for _, value := range values {