avaje-http icon indicating copy to clipboard operation
avaje-http copied to clipboard

Ordering of filters and weight of http features

Open re-thc opened this issue 1 year ago • 4 comments

Hi, in using @filter is there a way to specify the order? The helidon docs says that they get applied based the order they're added to Helidon. Is that then based on how we add the beans / HttpFeature? There's no way at the moment to sort it in some specific order.

More generally speaking, filters and controllers create Http Features, which have weights that impact ordering. Is there any way to set this?

Also is each controller a HttpFeature? Can we group things?

Thanks!

re-thc avatar Oct 01 '24 09:10 re-thc

Each controller is indeed a http feature, with each route within the controller registered in order of appearance. Filters are technically categorized as a route as well so you can group everything into a single controller.

SentryMan avatar Oct 01 '24 12:10 SentryMan

Weight of regular controller routes rarely matter, as filters always go before routes even if registered after

SentryMan avatar Oct 01 '24 13:10 SentryMan

Yes, we will need a way to order @Filters and that might be missing. For avaje-inject there is a @Priority and ability to get a list of components ordered by the priority value so that might be all that we are after at this stage.

For avaje-nima when adding HttpFeatures we'd change that from using beanScope.list(HttpFeature.class) to beanScope.listByPriority(HttpFeature.class).

rbygrave avatar Oct 08 '24 10:10 rbygrave

Perhaps we are over thinking it in that the simplest approach is to have a dedicated controller for filters [and perhaps exceptions] and the order of the filter methods there is the order in which they are registered.

For example:

@Controller
final class ErrorController {

  @ExceptionHandler(statusCode = 407)
  Map<String, Object> runEx(RuntimeException ex, ServerRequest req, ServerResponse res) {
    return Map.of("err", String.valueOf(ex));
  }

  @Filter
  void filter1(FilterChain chain, RoutingResponse res) {
    chain.proceed();
  }

  @Filter
  void filter2(FilterChain chain, RoutingResponse res) {
    chain.proceed();
  }

  @Filter
  void filter(FilterChain chain, RoutingResponse res) {
    chain.proceed();
  }
}

generates ...

  @Override
  public void setup(HttpRouting.Builder routing) {
    routing.error(RuntimeException.class, this::_runEx);
    routing.addFilter(this::_filter1);
    routing.addFilter(this::_filter2);
    routing.addFilter(this::_filter);
  }

... so the order of the filters registered just matches the order in which they are defined in source.

rbygrave avatar Dec 03 '24 09:12 rbygrave

Perhaps we are over thinking it in that the simplest approach is to

Closing unless more details are added for why the above wouldn't work

SentryMan avatar May 12 '25 02:05 SentryMan