title: Is there a way to apply a filter or code BEFORE routing (Spring Cloud Gateway)
body: <p>I'm writing an API Gateway that must route requests based on a MAC address. Example of endpoints:</p>
  <pre><code>/api/v2/device/AABBCCDDEEFF
  /api/v2/device/AABBCCDDEEFF/metadata
  /api/v2/device/search?deviceId=AABBCCDDEEFF
  </code></pre>
  <p>I've written a <a href="https://cloud.spring.io/spring-cloud-gateway/reference/html/#gateway-request-predicates-factories" rel="nofollow noreferrer">Custom Predicate Factory</a> that extracts the MAC address, performs the necessary logic to determine what URL the MAC address should be routed to, then stores that information on the <code>ServerWebExchange</code> attributes.</p>
  <pre class="lang-java prettyprint-override"><code>public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory&lt;CustomRoutePredicateFactory.Config&gt; {
      // Fields/Constructors Omitted
  
      private static final String IP_ATTRIBUTE = &quot;assignedIp&quot;;
      private static final String MAC_ATTRIBUTE = &quot;mac&quot;;
  
      @Override
      public Predicate&lt;ServerWebExchange&gt; apply(Config config) {
          return (ServerWebExchange exchange) -&gt; {
              String mac = exchange.getAttributes().get(MAC_ATTRIBUTE);
              if(mac == null){
                  mac = extractMacAddress(exchange);
              }
  
              if(!exchange.getAttributes().contains(IP_ATTRIBUTE)){
                  exchange.getAttributes().put(IP_ATTRIBUTE, findAssignedIp(mac);
              }
  
              return config.getRouteIp().equals(exchange.getAttribute(IP_ATTRIBUTE));
          });
      }
      // Config Class &amp; utility methods omitted
  }
  </code></pre>
  <p><em>NOTE: This implementation is greatly simplified for brevity</em></p>
  <p>With this implementation I'm able to guarantee that the MAC is extracted only once and the logic determining what URL the request belongs to is performed only once. The first call to the predicate factory will extract and set that information on ServerWebExchange Attributes and any further calls to the predicate factory will detect those attributes and use them to determine if they match.</p>
  <p>This works, but it isn't particularly neat. It would be much easier and simpler if I could somehow set the Exchange Attributes on every single request entering the gateway <strong>BEFORE</strong> the application attempts to match routes. Then the filter could be a simple predicate that checks for equality on the Exchange Attributes.</p>
  <p>I've read through the documentation several times, but nothing seems to be possible. Filters are always scoped to a particular route and run only after a route matches. It might be possible to make the first route be another Predicate that executes the necessary code, sets the expected attributes and always returns false, but can I guarantee that this predicate is <strong>always</strong> run <strong>first</strong>? It seems like there should be support for this kind of use case, but I cannot for the life of me find a way that doesn't seem like a hack. Any ideas?</p>