Skip to content

Commit 686eb1b

Browse files
reyortiz3claude
andauthored
Restore ServerBuilder.WithMiddleware and WithRoute (#5369)
* Restore ServerBuilder.WithMiddleware and WithRoute These two methods are the only public API available to ApplyServerExtensions hooks (the enterprise overlay uses them to inject session-auth middleware and mount an /enterprise sub-router). #5355 dropped them as unreachable because the only callers live behind //go:build enterprise, which upstream CI does not exercise. Add a unit test that exercises both methods so future deadcode passes see them as live, and add doc comments explaining the extension-point contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Reword comments to describe the public extension contract Reframe the doc comments and test rationale around the public extension point itself ("ApplyServerExtensions consumers", "downstream repositories") rather than the internal identity of any particular consumer. The behavior of the methods is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b9ec592 commit 686eb1b

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

pkg/api/server.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,35 @@ func (b *ServerBuilder) WithOtelEnabled(enabled bool) *ServerBuilder {
142142
return b
143143
}
144144

145+
// WithMiddleware appends HTTP middleware that runs after the default middleware
146+
// stack (request-ID, body-size limit, headers, update-check, auth) and before
147+
// route handlers. Part of the ApplyServerExtensions extension point — used by
148+
// downstream consumers to inject custom authentication or request-scoping
149+
// middleware into the API server.
150+
//
151+
// Public extension API. Do not remove based on deadcode analysis alone:
152+
// callers may live in repositories that are not visible to this module's
153+
// analyzer. The test in server_test.go intentionally exercises this method
154+
// to keep it reachable.
155+
func (b *ServerBuilder) WithMiddleware(mw ...func(http.Handler) http.Handler) *ServerBuilder {
156+
b.middlewares = append(b.middlewares, mw...)
157+
return b
158+
}
159+
160+
// WithRoute mounts a sub-router at the given prefix. The caller is responsible
161+
// for any per-route timeout middleware. Part of the ApplyServerExtensions
162+
// extension point — used by downstream consumers to add API surface alongside
163+
// the built-in routes.
164+
//
165+
// Public extension API. Do not remove based on deadcode analysis alone:
166+
// callers may live in repositories that are not visible to this module's
167+
// analyzer. The test in server_test.go intentionally exercises this method
168+
// to keep it reachable.
169+
func (b *ServerBuilder) WithRoute(prefix string, handler http.Handler) *ServerBuilder {
170+
b.customRoutes[prefix] = handler
171+
return b
172+
}
173+
145174
// Build creates and configures the HTTP router
146175
func (b *ServerBuilder) Build(ctx context.Context) (*chi.Mux, error) {
147176
r := chi.NewRouter()

pkg/api/server_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ package api
66
import (
77
"fmt"
88
"net"
9+
"net/http"
910
"regexp"
1011
"testing"
1112

13+
"github.com/go-chi/chi/v5"
1214
"github.com/stretchr/testify/assert"
1315
"github.com/stretchr/testify/require"
1416
)
@@ -86,3 +88,43 @@ func TestListenURL(t *testing.T) {
8688
})
8789
}
8890
}
91+
92+
// TestServerBuilderExtensionPoints exercises WithMiddleware and WithRoute so
93+
// they remain reachable to deadcode analysis. Both methods form the public
94+
// surface for ApplyServerExtensions consumers, whose callers may live in
95+
// downstream repositories that this module's analyzer cannot see. Without
96+
// this test, a future deadcode pass would flag them as unreachable (as
97+
// happened in #5355) even though external callers depend on them.
98+
func TestServerBuilderExtensionPoints(t *testing.T) {
99+
t.Parallel()
100+
101+
t.Run("WithMiddleware appends to middleware chain", func(t *testing.T) {
102+
t.Parallel()
103+
104+
b := NewServerBuilder()
105+
mw := func(next http.Handler) http.Handler { return next }
106+
b.WithMiddleware(mw, mw)
107+
108+
assert.Len(t, b.middlewares, 2)
109+
})
110+
111+
t.Run("WithRoute registers handler at prefix", func(t *testing.T) {
112+
t.Parallel()
113+
114+
b := NewServerBuilder()
115+
b.WithRoute("/ext", chi.NewRouter())
116+
117+
_, ok := b.customRoutes["/ext"]
118+
assert.True(t, ok, "expected /ext to be registered")
119+
})
120+
121+
t.Run("methods chain on the builder", func(t *testing.T) {
122+
t.Parallel()
123+
124+
b := NewServerBuilder().
125+
WithMiddleware(func(next http.Handler) http.Handler { return next }).
126+
WithRoute("/ext", chi.NewRouter())
127+
128+
assert.NotNil(t, b)
129+
})
130+
}

0 commit comments

Comments
 (0)