Explain the After/Before/Between temporal predicates and how Path/Host capture variables for downstream use.
answer
- After/Before/Between vs ZonedDateTime (now)
- Between = start inclusive, end exclusive
- gateway clock + timezone matter
- Path {segment}, Host {sub} capture
- captures -> URI_TEMPLATE_VARIABLES_ATTRIBUTE -> SetPath/RewritePath
basics
~20 sAfter, Before, and Between compare the current time to a ZonedDateTime: After matches requests after it, Before matches before it, Between matches within a window. Path and Host patterns can capture named variables (like {segment}) that filters can reuse.
solid answer
~40 sThe temporal predicates match on the request's arrival time against a ZonedDateTime (ISO-8601 with zone/offset). After=<datetime> matches requests received strictly after that instant; Before=<datetime> matches before it; Between=<start>,<end> matches inside the half-open window. They're handy for scheduled cut-overs, maintenance windows, or timed feature launches without redeploying. Separately, Path patterns like /red/{segment} and Host patterns like {sub}.example.org capture named variables using PathPattern / URI-template matching. Captured values are stored in exchange attributes (URI_TEMPLATE_VARIABLES_ATTRIBUTE), and variable-aware filters — RewritePath, SetPath, and templated header filters — can reference {segment} or {sub} to build the downstream request. This lets you route and rewrite dynamically off parts of the incoming URL or hostname.
code
java · 13 lines@Bean
RouteLocator routes(RouteLocatorBuilder b) {
ZonedDateTime launch = ZonedDateTime.parse("2030-01-01T00:00:00Z");
return b.routes()
// Timed launch: only active after 'launch'
.route("promo", r -> r.path("/promo/**").and().after(launch)
.uri("lb://promo-service"))
// Capture {segment} and reuse it in SetPath
.route("rewrite", r -> r.path("/red/{segment}")
.filters(f -> f.setPath("/{segment}")) // /red/blue -> /blue
.uri("lb://color-service"))
.build();
}go deeper
May not know temporal predicates exist.
Knows After/Before/Between compare to a datetime.
Explains ZonedDateTime parsing, window boundaries, and Path/Host capture flowing into filters.
Designs timed cut-overs accounting for clock skew/refresh and uses captures for dynamic rewrite pipelines.
**Temporal predicates** compare the moment the request is processed to a configured `ZonedDateTime`: - **After** (`AfterRoutePredicateFactory`): `After=2030-01-20T17:42:47.789-07:00[America/Denver]` — matches when *now* is **after** that datetime. - **Before** (`BeforeRoutePredicateFactory`): matches when *now* is **before** the datetime. - **Between** (`BetweenRoutePredicateFactory`): `Between=<start>,<end>` — matches when *now* is at/after start and **before** end (start inclusive, end exclusive; start must be before end). The datetime string is parsed to a `ZonedDateTime` (default parser is `ZonedDateTime.parse`, ISO-8601, honoring the offset/zone like `[America/Denver]`). In the DSL: `.after(ZonedDateTime.now().plusDays(1))`, `.before(...)`, `.between(start, end)`. **Use cases:** turn a route on/off at a scheduled time, blue/green or maintenance windows, timed promotions — all without a redeploy (especially combined with `/actuator/gateway/refresh` for YAML changes). **Gotchas:** matching uses the **gateway's clock and zone**, so clock skew and server timezone matter; the values are static config, so a still-running instance keeps whatever was loaded until refreshed/restarted. **Capture variables** — Path and Host patterns aren't just true/false tests; they can **extract** parts of the request: - **Path**: `Path=/red/{segment}` matches `/red/anything` and captures `segment`. You can constrain with regex: `{segment:[a-z]+}`. The `**` wildcard can also be referenced via `{**remaining}` style captures in path rewrites. - **Host**: `Host={sub}.example.org` captures the subdomain into `sub`. Captured values are placed into **exchange attributes** under `ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE` (a `Map<String,String>`). **Variable-aware filters** then reference them with `{name}` syntax: - `RewritePath=/red/(?<seg>.*), /$\{seg}` (regex-based rewrite), or - `SetPath=/{segment}` which substitutes the captured `segment`, or - header filters like `AddRequestHeader=X-Sub, {sub}`. This is the mechanism behind dynamic routing: match a URL/host shape, capture the meaningful part, and rebuild the downstream path or headers from it. **Gotcha:** the variable name in the predicate must exactly match the placeholder used by the filter, and only *capture-aware* factories (Path, Host) populate `URI_TEMPLATE_VARIABLES_ATTRIBUTE` — Header/Query/Method don't expose captures the same way.
- Between=start,end — is the window inclusive or exclusive at each end?Start is inclusive, end is exclusive (half-open); start must be chronologically before end or it won't match.
- How does a filter access a {segment} captured by a Path predicate?The capture is stored in the exchange attribute URI_TEMPLATE_VARIABLES_ATTRIBUTE; variable-aware filters like SetPath or AddRequestHeader reference it by name with {segment} placeholder syntax.
saying these in an interview costs you the question
- Thinking After/Before compare to a client-supplied timestamp rather than the gateway's current time
- Assuming Between is fully inclusive on both ends
- Believing Header/Query captures are available to RewritePath like Path/Host captures
- Ignoring server timezone/clock skew for temporal matching