Part of duplicate code analysis: #1283
Summary
The sdk.NewStreamableHTTPHandler callback used to establish HTTP sessions is nearly identical in transport.go (unified mode) and routed.go (routed mode). Both callbacks perform the same sequence of operations — extract+validate session, log the connection, log the request body, inject context — with only cosmetic differences.
Duplication Details
Pattern: StreamableHTTP session-setup callback
- Severity: Medium
- Occurrences: 2
- Locations:
internal/server/transport.go (lines 85–108)
internal/server/routed.go (lines 110–130)
transport.go (unified):
sessionID := extractAndValidateSession(r)
if sessionID == "" {
return nil
}
logger.LogInfo("client", "MCP connection established, remote=%s, method=%s, path=%s, session=%s", ...)
log.Printf("=== NEW STREAMABLE HTTP CONNECTION ===")
log.Printf("[%s] %s %s", r.RemoteAddr, r.Method, r.URL.Path)
log.Printf("Authorization (Session ID): %s", sanitize.TruncateSecret(sessionID))
log.Printf("DEBUG: About to check request body, Method=%s, Body!=nil: %v", ...)
logHTTPRequestBody(r, sessionID, "")
*r = *injectSessionContext(r, sessionID, "")
log.Printf("✓ Injected session ID into context")
log.Printf("==========================\n")
return unifiedServer.server
routed.go (routed):
sessionID := extractAndValidateSession(r)
if sessionID == "" {
return nil
}
logger.LogInfo("client", "New MCP client connection, remote=%s, method=%s, path=%s, backend=%s, session=%s", ...)
log.Printf("=== NEW STREAMABLE HTTP CONNECTION (ROUTED) ===")
log.Printf("[%s] %s %s", r.RemoteAddr, r.Method, r.URL.Path)
log.Printf("Backend: %s", backendID)
log.Printf("Authorization (Session ID): %s", sessionID)
logHTTPRequestBody(r, sessionID, backendID)
*r = *injectSessionContext(r, sessionID, backendID)
log.Printf("✓ Injected session ID and backend ID into context")
log.Printf("===================================\n")
return serverCache.getOrCreate(...)
The only differences are: the log message text, whether backendID is passed, and the return value. The structural logic is identical.
Impact Analysis
- Maintainability: Any change to how sessions are logged (e.g. adding a trace ID, changing log formats) must be applied in both places. This has already led to minor inconsistencies (e.g.
sanitize.TruncateSecret used in one but not the other).
- Bug Risk: If validation logic in
extractAndValidateSession is changed and callers are updated separately, the two callbacks could diverge silently.
- Code Bloat: Minor (~15 lines duplicated).
Refactoring Recommendations
-
Extract a setupSession helper in http_helpers.go:
// setupSession handles the common session establishment logic for both unified and routed modes.
// It extracts and validates the session, logs the connection, and injects context.
// Returns the modified request and session ID, or empty string on failure.
func setupSession(r *http.Request, backendID string) (*http.Request, string) {
sessionID := extractAndValidateSession(r)
if sessionID == "" {
return r, ""
}
if backendID != "" {
logger.LogInfo("client", "New MCP client connection, remote=%s, ..., backend=%s, session=%s", ...)
} else {
logger.LogInfo("client", "MCP connection established, remote=%s, ..., session=%s", ...)
}
logHTTPRequestBody(r, sessionID, backendID)
r = injectSessionContext(r, sessionID, backendID)
return r, sessionID
}
Then callers become:
r, sessionID := setupSession(r, backendID) // or "" for unified
if sessionID == "" { return nil }
-
Estimated effort: ~30 minutes
-
Benefits: Single place to update session logging format; consistent use of sanitize.TruncateSecret; cleaner callbacks
Implementation Checklist
Parent Issue
See parent analysis report: #1283
Part of duplicate code analysis: #1283
Summary
The
sdk.NewStreamableHTTPHandlercallback used to establish HTTP sessions is nearly identical intransport.go(unified mode) androuted.go(routed mode). Both callbacks perform the same sequence of operations — extract+validate session, log the connection, log the request body, inject context — with only cosmetic differences.Duplication Details
Pattern: StreamableHTTP session-setup callback
internal/server/transport.go(lines 85–108)internal/server/routed.go(lines 110–130)transport.go(unified):routed.go(routed):The only differences are: the log message text, whether
backendIDis passed, and the return value. The structural logic is identical.Impact Analysis
sanitize.TruncateSecretused in one but not the other).extractAndValidateSessionis changed and callers are updated separately, the two callbacks could diverge silently.Refactoring Recommendations
Extract a
setupSessionhelper inhttp_helpers.go:Then callers become:
Estimated effort: ~30 minutes
Benefits: Single place to update session logging format; consistent use of
sanitize.TruncateSecret; cleaner callbacksImplementation Checklist
setupSessionhelper intointernal/server/http_helpers.gotransport.goandrouted.gocallbacks to call the helperParent Issue
See parent analysis report: #1283