title: Spring Cloud Gateway - unhappy path handling in filters (Exception Handling vs Response manipulation) with Response body
body: <p>What is the best (aka most efficient way) of implementing the management of unhappy paths with SCG Filters and Response with a body? Exception handling or response rewriting?</p>
  <h1>Scenario</h1>
  <p>We are implementing an API Gateway with some complex GatewayFilters (between different type of Throttling and some other behaviours) that have in common an unhappy path where they terminate the exchange chain processing and should return immediately a 4xx response with a specific common body format (json/xml based on Accept header, we have legacy compatibility requirements).</p>
  <h2>Initial solution</h2>
  <p>My initial solution was to use the filter and then try to write the response with one of those options:</p>
  <pre class="lang-java prettyprint-override"><code>response.setStatusCode(..);
  //set headers
  return response.writeAndFlushWith(...);
  </code></pre>
  <p>or</p>
  <pre class="lang-java prettyprint-override"><code>response.setStatusCode(..);
  //set headers
  return response.writeWith(...);
  </code></pre>
  <p>or even</p>
  <pre class="lang-java prettyprint-override"><code>response.setStatusCode(..);
  exchange.mutate().response(...);
  return response.setComplete();
  </code></pre>
  <p>in each specific filter.
  But the processing of the body response seems quite a verbose process, plus the formatting of the error provided by the filter should not be a concern of the specific filter.
  We want a separation of concerns, so the filter should be defining headers, status and error message but someone else should transform that in the proper response format.</p>
  <p>So after a long (and bloody :) ) discussion we come up with two possible options.
  Let's assume we have 4 Filters and our happy path would be (with some approximation non considering overlapping from global filters order):</p>
  <p><code>(initial global filters) -&gt; 1 -&gt; 2 -&gt; 3 -&gt; 4-&gt; 5 -&gt; (other global filters) -&gt; Routing -&gt; (other global filters) -&gt; 5 -&gt; 4-&gt; 3 -&gt; 2 -&gt; 1 -&gt; 0 -&gt; (initial global filters) -&gt; Response</code></p>
  <h3>Option 1 - Error Handling</h3>
  <p>Implement a class <code>java MyErrorHandler extends DefaultErrorWebExceptionHandler</code> and <code>java MyErrorAttributes extends DefaultErrorAttributes</code> and that does the magic.</p>
  <p>This means in the specific filter throwing an exception that extends <code>ResponseStatusException </code> or is annotated with <code>@ResponseStatus</code> and have it bubble out to the ExceptionHandler
  This has the advantage of interrupting all the exchange processing in the filters, too, if I am not wrong.
  Eg: given 3 filters and filter 3 throwing an exception we have
  <code>... 1 -&gt; 2 -&gt; 3 -&gt; ExH -&gt; (other global filters) -&gt; Response</code></p>
  <h3>Option 2 - Response Writing</h3>
  <p>Add a filter (filter 0) in the topmost position, maybe one extending <code>ModifyResponseGatewayFilter</code> that manages errors writing in the response by looking at a specific <em>exchange attribute</em> (eg:<code>gateway.error</code>) for a bean and writes the response, and have the filter in the chain set that specific bean and generate the response with that.</p>
  <p>This would have the following flow :
  <code>... -&gt; 0 -&gt; 1 -&gt; 2 -&gt; 3 -&gt; 2 -&gt; 1 -&gt; 0 -&gt; (other global filters) -&gt; Response</code></p>
  <h2>Issues</h2>
  <p>Option</p>
  <ol>
  <li>Option 1 seems the short circuit option that really blocks the processing and builds on existing capabilities (ExceptionHandler) but I am told Exceptions are a terrible burden for efficiency since they are forced to build all the stacktrace</li>
  <li>Option 2 seems to be more efficient, but then the response bubbles up through all the &quot;post&quot; filters and we must make sure that no other filter tries to update the response by checking the specific <em>exchange attribute</em> (eg:<code>gateway.error</code>)</li>
  </ol>
  <p>The RedisRateLimiter offered by SCG uses option2 but does no body rewriting and uses <code>response.setComplete()</code> but this doesn't allow any body rewriting later.</p>
  <p>Is this the preferred approach?</p>