skip to content

GatewayFilter Factories

GatewayFilter factories rewrite a single route's request and response — adding headers, rewriting paths, stripping prefixes, redirecting — in a pre or post phase. This is where API-shape differences between the gateway and the backend get absorbed.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What are GatewayFilter factories in Spring Cloud Gateway, and how do you configure one like AddRequestHeader on a route?

level: juniorimportance: must knowfreq 70%

answer

  1. Per-route predicates + filters
  2. Named factories: AddRequestHeader, RewritePath, StripPrefix
  3. Shortcut syntax maps to shortcutFieldOrder
  4. Adds header to DOWNSTREAM request
  5. WebFlux/Netty, reactive

basics

~10 s

They are reusable filters you attach to a single route to change its request or response. For example, AddRequestHeader=X-Env,prod adds that header to every request forwarded through that route.

solid answer

~40 s

In Spring Cloud Gateway a route has predicates (when it matches) and filters (what to do with the matched request). GatewayFilter factories are the named, parameterized building blocks for those per-route filters. You configure them declaratively, usually in application.yml under spring.cloud.gateway.routes[].filters. Built-in examples include AddRequestHeader, RewritePath, StripPrefix, RedirectTo and SetStatus. Each factory reads its arguments (e.g. AddRequestHeader=X-Request-Env, prod) and produces a GatewayFilter that runs when the route matches. AddRequestHeader specifically adds a header to the request sent to the downstream service, not to the client's original view. Because filters are per-route, the same factory can be reused with different arguments on different routes, which keeps routing configuration declarative and composable.

code

kotlin · 10 lines
kotlin
// application.yml equivalent expressed via the Java/Kotlin route DSL
@Bean
fun routes(builder: RouteLocatorBuilder): RouteLocator =
    builder.routes()
        .route("users-route") { r ->
            r.path("/api/users/**")
                .filters { f -> f.addRequestHeader("X-Request-Env", "prod") }
                .uri("http://users-service:8080")
        }
        .build()

go deeper

for a junior

Should know filters are per-route and AddRequestHeader adds a header to the forwarded request.

for a middle

Should know shortcut vs expanded syntax and Add vs Set semantics.

for a senior

Should relate factories to the GatewayFilter/predicate model and reactive stack.

for a principal

Frames filters as declarative edge policy and knows the factory/shortcutFieldOrder mechanism.

**Spring Cloud Gateway** is an API gateway built on Spring WebFlux and Project Reactor (non-blocking, runs on Netty). It routes incoming requests to downstream services. A **route** has three parts: an id, a set of **predicates** (conditions like path, host, method that decide whether the route matches), and a set of **filters** (logic that mutates the request/response as it passes through). A **GatewayFilter factory** is a component that produces a `GatewayFilter` for one route. Each built-in factory is named `<Name>GatewayFilterFactory` and is referenced in config by its short name (`AddRequestHeader`, `RewritePath`, `StripPrefix`, `RedirectTo`, `SetStatus`, etc.). The factory pattern lets you parameterize the filter: you give it arguments and it returns a configured filter instance. **Typical YAML configuration:** ```yaml spring: cloud: gateway: routes: - id: users-route uri: http://users-service:8080 predicates: - Path=/api/users/** filters: - AddRequestHeader=X-Request-Env, prod ``` Here `AddRequestHeader=X-Request-Env, prod` means: for any request matching this route, add the header `X-Request-Env: prod` **to the request that is forwarded downstream**. This is the key semantic — it modifies the outbound (proxied) request, so the downstream service sees the header. The original client never set it and does not see it added to their own copy. **Shortcut vs full syntax.** The compact form `AddRequestHeader=X-Request-Env, prod` is a *shortcut*; the factory declares a `shortcutFieldOrder()` so positional args map to config fields. The equivalent expanded form is: ```yaml - name: AddRequestHeader args: name: X-Request-Env value: prod ``` **Per-route vs global.** GatewayFilter factories are per-route. A different mechanism, `GlobalFilter`, applies to every route (that is a separate concern and out of scope here). You can attach many filters to one route; they run in a chain. **When to use.** Use built-in GatewayFilter factories for common edge concerns without writing code: injecting headers for downstream services, rewriting/stripping path prefixes so the gateway's public path differs from the backend's internal path, issuing redirects, or overriding response status. **Gotchas.** AddRequestHeader *adds* (it does not replace) — a duplicate header can result if the client already sent one; use `SetRequestHeader` to overwrite. YAML values with commas or special characters may need quoting. The value supports property placeholders and, since it produces a request header, it affects only the proxied request.

  • What is the difference between AddRequestHeader and SetRequestHeader?
    AddRequestHeader appends a header value (can create duplicates if one already exists); SetRequestHeader overwrites/replaces any existing value for that header name.
  • Does AddRequestHeader modify the response the client receives?
    No. It modifies the request forwarded to the downstream service. For response headers you'd use AddResponseHeader.

saying these in an interview costs you the question

  • Thinking AddRequestHeader modifies the client's original request or the response
  • Confusing per-route GatewayFilter factories with GlobalFilters
  • Believing AddRequestHeader replaces an existing header (it appends)

context

open as a page

Explain the pre and post phases of a GatewayFilter and how you mutate the ServerWebExchange request versus response in each.

level: seniorimportance: must knowfreq 55%

basics

~20 s

A GatewayFilter can run logic before forwarding (pre) and after the response comes back (post). In the pre phase you mutate the request via exchange.mutate(); in the post phase (inside .then(...)) you touch the response after chain.filter completes.

open as a page

Contrast RedirectTo and SetStatus. What does each do to the response and request flow?

level: middleimportance: should knowfreq 45%

basics

~20 s

SetStatus just overrides the HTTP status code of the response the client gets, while still forwarding to the downstream. RedirectTo short-circuits the route: it returns a redirect (status + Location header) to the client and does not forward the request downstream.

open as a page

Compare StripPrefix and RewritePath. When would you choose one over the other?

level: middleimportance: should knowfreq 60%

basics

~20 s

Both change the path sent downstream. StripPrefix removes a fixed number of leading path segments. RewritePath uses a regex to transform the path into any shape. Use StripPrefix for simple prefix removal, RewritePath when you need pattern-based rewriting.

open as a page

How would you implement a custom GatewayFilter factory, and what are the key extension points (config binding, shortcut args, ordering)?

level: principalimportance: should knowfreq 35%

basics

~10 s

Extend AbstractGatewayFilterFactory<Config> with a nested Config POJO, register it as a @Component whose class name ends in GatewayFilterFactory, implement apply(config) to return the GatewayFilter, and override shortcutFieldOrder() to enable the compact YAML syntax.

open as a page