[[developer-guide]] = Developer Guide These are basic guides to writing some custom components of the gateway. [[writing-custom-route-predicate-factories]] == Writing Custom Route Predicate Factories In order to write a Route Predicate you will need to implement `RoutePredicateFactory` as a bean. There is an abstract class called `AbstractRoutePredicateFactory` which you can extend. .MyRoutePredicateFactory.java [source,java] ---- @Component public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory { public MyRoutePredicateFactory() { super(Config.class); } @Override public Predicate apply(Config config) { // grab configuration from Config object return exchange -> { //grab the request ServerHttpRequest request = exchange.getRequest(); //take information from the request to see if it //matches configuration. return matches(config, request); }; } public static class Config { //Put the configuration properties for your filter here } } ---- [[writing-custom-gatewayfilter-factories]] == Writing Custom GatewayFilter Factories To write a `GatewayFilter`, you must implement `GatewayFilterFactory` as a bean. You can extend an abstract class called `AbstractGatewayFilterFactory`. The following examples show how to do so: .PreGatewayFilterFactory.java ==== [source,java] ---- @Component public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory { public PreGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { // grab configuration from Config object return (exchange, chain) -> { //If you want to build a "pre" filter you need to manipulate the //request before calling chain.filter ServerHttpRequest.Builder builder = exchange.getRequest().mutate(); //use builder to manipulate the request return chain.filter(exchange.mutate().request(builder.build()).build()); }; } public static class Config { //Put the configuration properties for your filter here } } ---- .PostGatewayFilterFactory.java [source,java] ---- @Component public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory { public PostGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { // grab configuration from Config object return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> { ServerHttpResponse response = exchange.getResponse(); //Manipulate the response in some way })); }; } public static class Config { //Put the configuration properties for your filter here } } ---- ==== [[naming-custom-filters-and-references-in-configuration]] === Naming Custom Filters And References In Configuration Custom filters class names should end in `GatewayFilterFactory`. For example, to reference a filter named `Something` in configuration files, the filter must be in a class named `SomethingGatewayFilterFactory`. WARNING: It is possible to create a gateway filter named without the `GatewayFilterFactory` suffix, such as `class AnotherThing`. This filter could be referenced as `AnotherThing` in configuration files. This is **not** a supported naming convention and this syntax may be removed in future releases. Please update the filter name to be compliant. [[writing-custom-global-filters]] == Writing Custom Global Filters To write a custom global filter, you must implement `GlobalFilter` interface as a bean. This applies the filter to all requests. The following examples show how to set up global pre- and post-filters, respectively: [source,java] ---- @Bean public GlobalFilter customGlobalFilter() { return (exchange, chain) -> exchange.getPrincipal() .map(Principal::getName) .defaultIfEmpty("Default User") .map(userName -> { //adds header to proxied request ServerHttpRequest.Builder builder = exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName); //use builder to manipulate the request return exchange.mutate().request(builder.build()).build(); }) .flatMap(chain::filter); } @Bean public GlobalFilter customGlobalPostFilter() { return (exchange, chain) -> chain.filter(exchange) .then(Mono.just(exchange)) .map(serverWebExchange -> { //adds header to response serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER", HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work"); return serverWebExchange; }) .then(); } ----