Support nesting zio-http routes under a prefix - #5436
Open
adamw wants to merge 1 commit into
Open
Conversation
zio-http's Routes.nest only prepends segments to the route pattern; the Request passed to the handler keeps its full path. As the tapir interpreter re-matches the whole path itself, none of the endpoints matched, resulting in a 404 (or a 405, if the reject interceptor found a method mismatch first). The interpreter now computes per-request how many leading path segments come from the nesting prefix, and skips them when matching.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5435.
Problem
zio-http's
Routes.nest(prefix)(andPathCodec./) only rewrites the route pattern —RoutePattern.nestiscopy(pathCodec = prefix ++ pathCodec). TheRequestpassed to the handler keeps its full path.The tapir interpreter uses zio-http routing only to dispatch (
Route.handledIgnoreParams) and then re-matches the whole path itself, fromreq.url.path.segments. So after.nest("api"), an endpoint declared aspath[UUID](one segment) is matched against/api/<uuid>(two segments), and nothing matches.The reported symptom is
405 Method Not Allowedrather than404: with two or more endpoints the reject interceptor is active, and the first failure of the non-matching-method endpoint is on itsFixedMethodinput, soDefaultRejectHandlerreports a method mismatch. With a single endpoint (reject interceptor disabled) the same setup returns404. Nesting was broken in general, not just for this combination.Fix
The interpreter now computes, per request, how many leading path segments come from the nesting prefix, and skips them when matching. This can only be done per-request, as the pattern under which a route ends up being registered is not known when the route is created.
ZioHttpInterpreter: the generated route pattern now carries its shape (number of matched segments, and whether it ends with a trailing wildcard).context = requestSegments - patternSegmentspaths,noTrailingSlash, or endpoints with no path inputs): the wildcard absorbs the rest of the path, so its length is needed as well — such routes are created usingRoute.handled, whose decoded parameters include the trailingPath; thencontext = requestSegments - patternSegments - trailingSegmentsBoth are exact, for a prefix of any length.
ZioHttpServerRequest: gainscontextPathSegments(n), stored as an attribute, whichpathSegmentsskips.uriremains the full request URI — the same split that the http4s interpreter already uses for routes mounted in a context.Tests
ZioHttpCompositionTestcovers a path capture with two methods, a fixed path, apathswildcard and an endpoint without path inputs, all under.nest("api"), plus a check that un-prefixed paths still yield a 404. The test fails on master with405 was not equal to 200.