fix(matcher,server): use ConflictError in AddNamed and add tests

Make AddNamed return *ConflictError for consistency with other Add*
methods so handleRegistrationError treats named location conflicts as
warnings instead of fatal errors. Add tests for handleRegistrationError
covering both conflict and fatal error paths.
This commit is contained in:
xfy 2026-06-03 11:47:06 +08:00
parent f58f194752
commit 556d40ceb0
2 changed files with 29 additions and 2 deletions

View File

@ -173,8 +173,12 @@ func (e *LocationEngine) AddNamed(name string, handler fasthttp.RequestHandler)
return errors.New("LocationEngine already initialized") return errors.New("LocationEngine already initialized")
} }
if existing, ok := e.namedMatchers[name]; ok { if _, ok := e.namedMatchers[name]; ok {
return fmt.Errorf("named location '@%s' already registered", existing.name) return &ConflictError{
Path: "@" + name,
ExistingType: "named",
NewType: "named",
}
} }
matcher := NewNamedMatcher(name, handler) matcher := NewNamedMatcher(name, handler)

View File

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"net" "net"
"os" "os"
"strings"
"sync" "sync"
"testing" "testing"
"time" "time"
@ -26,6 +27,7 @@ import (
"rua.plus/lolly/internal/config" "rua.plus/lolly/internal/config"
"rua.plus/lolly/internal/loadbalance" "rua.plus/lolly/internal/loadbalance"
"rua.plus/lolly/internal/lua" "rua.plus/lolly/internal/lua"
"rua.plus/lolly/internal/matcher"
"rua.plus/lolly/internal/middleware/accesslog" "rua.plus/lolly/internal/middleware/accesslog"
"rua.plus/lolly/internal/middleware/security" "rua.plus/lolly/internal/middleware/security"
"rua.plus/lolly/internal/proxy" "rua.plus/lolly/internal/proxy"
@ -989,6 +991,27 @@ func TestCreateListener_UnixSocketCleanup(t *testing.T) {
defer ln.Close() defer ln.Close()
} }
func TestHandleRegistrationError_ConflictWarning(t *testing.T) {
s := &Server{}
err := s.handleRegistrationError("proxy", "/api",
&matcher.ConflictError{Path: "/api", ExistingType: "exact", NewType: "prefix"})
if err != nil {
t.Errorf("conflict should return nil, got: %v", err)
}
}
func TestHandleRegistrationError_FatalError(t *testing.T) {
s := &Server{}
err := s.handleRegistrationError("proxy", "/api",
fmt.Errorf("invalid regex pattern: missing closing parenthesis"))
if err == nil {
t.Error("fatal error should return non-nil")
}
if !strings.Contains(err.Error(), "proxy route /api") {
t.Errorf("error should wrap context, got: %v", err)
}
}
func TestDupListener_TCP(t *testing.T) { func TestDupListener_TCP(t *testing.T) {
ln, err := net.Listen("tcp", "127.0.0.1:0") ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil { if err != nil {