Walk through the Path, Host, Method, Header, and Query predicate factories — what each matches and how they combine.
answer
- Path=PathPattern (**, {var}), not regex
- Host = Host header, Ant patterns
- Method = HttpMethod list
- Header/Query = name + optional value regex
- same route = AND; DSL and()/or()/negate()
basics
~20 sPath matches the URL path (Ant-style / PathPattern). Host matches the Host header. Method matches the HTTP verb. Header matches a header's presence/regex. Query matches a query parameter's presence/regex. Multiple predicates on one route are AND-ed.
solid answer
~40 sEach predicate factory tests one aspect of the incoming exchange. Path uses Spring's PathPatternParser to match the request path (`/api/**`, `/users/{id}`, capturing path variables). Host matches the HTTP Host header with Ant-style patterns (`**.example.org`) and can capture URI variables. Method matches one or more HttpMethod values (`GET,POST`). Header takes a header name plus an optional value regex — with no regex it just checks presence. Query takes a param name plus optional value regex, again presence-only if the regex is omitted. On a single route these predicates are combined with logical AND, so the route matches only when every one is satisfied. In the Java DSL you chain them with `.and()`, and you can also `.or()` or `.negate()`. Path and Host expose captured variables that filters like RewritePath or SetPath can reference.
code
java · 13 lines@Bean
RouteLocator routes(RouteLocatorBuilder b) {
return b.routes()
.route("api", r -> r
.path("/api/{segment}") // Path + capture
.and().host("**.example.org") // Host header
.and().method(HttpMethod.GET) // HTTP verb
.and().header("X-Request-Id", "\\d+") // header value regex
.and().query("debug") // query param present
.uri("lb://api-service"))
.build();
// route matches only when ALL five conditions hold (logical AND)
}go deeper
Knows Path and Method exist and match path/verb.
Must distinguish PathPattern from regex and know Header/Query presence-vs-regex and AND semantics.
Discusses captured variables, PathPatternParser, and DSL and()/or()/negate() composition.
Advises on predicate design (narrowing, spoofable Host, separate routes vs boolean chains) for a large route table.
Every predicate is produced by a `RoutePredicateFactory` and evaluated against the `ServerWebExchange`. The core ones: **Path** (`PathRoutePredicateFactory`, shortcut `Path`): matches the request URI path using Spring's **`PathPatternParser`** (the same engine as WebFlux routing). Supports `?` (one char), `*` (segment), `**` (multiple segments), and **capture variables** `{name}` and `{name:regex}`. Example `Path=/red/{segment}` matches `/red/blue` and exposes `segment=blue`. Multiple patterns allowed: `Path=/first/**,/second/**`. There's a `matchTrailingSlash` option (default true) controlling whether `/foo` also matches `/foo/`. **Host** (`HostRoutePredicateFactory`, shortcut `Host`): matches the **`Host` header** (virtual-host routing) using Ant-style patterns via `PathMatcher`, so `**.example.org` matches `www.example.org`. Supports URI template variables `{sub}.example.org` which capture `sub` for downstream use. Multiple patterns comma-separated. **Method** (`MethodRoutePredicateFactory`, shortcut `Method`): matches the HTTP method. One or more values: `Method=GET,POST`. In the DSL: `.method(HttpMethod.GET, HttpMethod.POST)`. **Header** (`HeaderRoutePredicateFactory`, shortcut `Header`): first arg is the **header name**, optional second arg is a **regex** the header value must match. `Header=X-Request-Id, \d+` matches when `X-Request-Id` is present and all-digits. Omitting the regex (`Header=X-Request-Id`) matches whenever the header exists at all. Case-insensitive header name lookup. **Query** (`QueryRoutePredicateFactory`, shortcut `Query`): first arg is the **query parameter name**, optional second arg is a **regex** for its value. `Query=green` matches if `?green` (or `?green=anything`) is present; `Query=red, gree.` matches when `red`'s value matches the regex `gree.` (e.g. `red=greet`). **Combination semantics:** predicates listed on the **same route AND together** — the route matches only if all are true. In YAML this is implicit (each list item is another AND term). In the Java DSL, methods chained after `.and()` AND; `.or()` and `.negate()` let you build OR groups or invert. Note: `.and()`/`.or()` follow normal fluent precedence — for complex logic prefer separate routes over deeply nested boolean chains for readability. **Gotchas:** - Path uses `PathPattern` semantics, **not** raw regex — `**` is a path wildcard, not `.*`. - Header/Query **value** args ARE regexes and must fully match per `String.matches` semantics (implicitly anchored). - Host matches the `Host` **header**, which can be spoofed by clients — don't use it as a security boundary. - Adding predicates only **narrows** matching; you never widen a route by adding a predicate. - Captured Path/Host variables are stored in the exchange attributes (`URI_TEMPLATE_VARIABLES_ATTRIBUTE`) and usable by variable-aware filters.
- If a Header predicate has no regex argument, what does it match?It matches any request that simply carries that header, regardless of value — it's a presence check. The optional second regex arg further constrains the value.
- Is the Path predicate a regular expression?No. It's a Spring PathPattern (PathPatternParser): '*' = one path segment, '**' = many, '{name}' captures a segment. Header/Query VALUE args, however, are true regexes.
- Why shouldn't Host be trusted for authorization?The Host header is client-supplied and easily spoofed; it's fine for virtual-host routing but must not be a security/authz decision point.
saying these in an interview costs you the question
- Treating Path patterns as regex (using .* instead of **)
- Saying Header always requires a value (presence-only is valid)
- Believing predicates on one route are OR-ed
- Using Host header as a trust/security boundary