From 5adefb3e88d5f2a9e7139484b0dd5acb8c224e00 Mon Sep 17 00:00:00 2001 From: "yuxuan.wang1" Date: Mon, 3 Nov 2025 11:15:27 +0800 Subject: [PATCH] optimize: add default NoRoute and NoMethod handles to assist troubleshooting --- pkg/route/engine.go | 18 ++++++++++++++++++ pkg/route/engine_test.go | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/pkg/route/engine.go b/pkg/route/engine.go index 7dfe043fa..849e4eb58 100644 --- a/pkg/route/engine.go +++ b/pkg/route/engine.go @@ -402,6 +402,16 @@ func (engine *Engine) Init() error { engine.options.TLS.NextProtos = append(engine.options.TLS.NextProtos, suite.HTTP1) } + if len(engine.noRoute) <= 0 { + engine.noRoute = []app.HandlerFunc{hertzRouteNotFound} + engine.rebuild404Handlers() + } + + if len(engine.noMethod) <= 0 { + engine.noMethod = []app.HandlerFunc{hertzNotAllowedMethod} + engine.rebuild405Handlers() + } + if !atomic.CompareAndSwapUint32(&engine.status, 0, statusInitialized) { return errInitFailed } @@ -417,6 +427,14 @@ func (engine *Engine) listenAndServe() error { return engine.transport.ListenAndServe(engine.onData) } +// hertzRouteNotFound is default NoRoute handler when users do not configure any handler with NoRoute. +// it is not an anonymous function, so utils.NameOfFunction could obtain a specific function name to assist troubleshooting. +func hertzRouteNotFound(c context.Context, ctx *app.RequestContext) {} + +// hertzNotAllowedMethod is default NoMethod handler when users do not configure any handler with NoMethod. +// it is not an anonymous function, so utils.NameOfFunction could obtain a specific function name to assist troubleshooting. +func hertzNotAllowedMethod(c context.Context, ctx *app.RequestContext) {} + func (c *hijackConn) Close() error { if !c.e.KeepHijackedConns { // when we do not keep hijacked connections, diff --git a/pkg/route/engine_test.go b/pkg/route/engine_test.go index 172209a3f..956a07b95 100644 --- a/pkg/route/engine_test.go +++ b/pkg/route/engine_test.go @@ -49,6 +49,7 @@ import ( "io/ioutil" "net" "net/http" + "strings" "sync" "sync/atomic" "testing" @@ -62,6 +63,7 @@ import ( errs "github.com/cloudwego/hertz/pkg/common/errors" "github.com/cloudwego/hertz/pkg/common/test/assert" "github.com/cloudwego/hertz/pkg/common/test/mock" + "github.com/cloudwego/hertz/pkg/common/utils" "github.com/cloudwego/hertz/pkg/network" "github.com/cloudwego/hertz/pkg/network/standard" "github.com/cloudwego/hertz/pkg/protocol" @@ -517,6 +519,22 @@ func TestSetEngineRun(t *testing.T) { assert.True(t, e.IsRunning()) } +func TestEngine_InitNoRouteAndNoMethod(t *testing.T) { + e := NewEngine(config.NewOptions(nil)) + err := e.Init() + assert.Assert(t, err == nil, err) + assert.Assert(t, len(e.allNoRoute) == 1, e.allNoRoute) + hdlName := utils.NameOfFunction(e.allNoRoute[0]) + pos := strings.LastIndexByte(hdlName, '.') + assert.Assert(t, pos >= 0, hdlName) + assert.Assert(t, hdlName[pos+1:] == "hertzRouteNotFound", hdlName) + assert.Assert(t, len(e.allNoMethod) == 1, e.allNoMethod) + hdlName = utils.NameOfFunction(e.allNoMethod[0]) + pos = strings.LastIndexByte(hdlName, '.') + assert.Assert(t, pos >= 0, hdlName) + assert.Assert(t, hdlName[pos+1:] == "hertzNotAllowedMethod", hdlName) +} + type mockConn struct{} func (m *mockConn) SetWriteTimeout(t time.Duration) error {