Mikhail Selivanov
Mikhail Selivanov

Reputation: 644

Why filter chain is called twice for an asynchronous endpoint

I'm developing a Spring boot based app. I noticed that for asynchronous endpoints authentication filter is called twice, for regular endpoints it's called once. I couldn't find the reason, but I found an issue in the net https://jira.spring.io/browse/SPR-12608 , where it's said that filters for async endpoints are called twice, before and after async endpoint execution. It would explain double authentication call. I'd like to know is this expected behavior, why it's done like that and how to avoid double authentication.

UPD: I found a way how to avoid filter being firing second time after async endpoint finished. The thing I need to do is to analyse what kind of dispatcher is assigned to the request, if it's async - proceed further on filter chain. I added the following method to the filter:

@Override
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
    if (request.getDispatcherType() == DispatcherType.ASYNC) {
        filterChain.doFilter(request, response);
    } else {
        super.doFilter(request, response, filterChain);
    }
}

Upvotes: 5

Views: 2841

Answers (2)

David Sanchez
David Sanchez

Reputation: 11

I had the same problem with a concrete implementation of the class AbstractAuthenticationProcessingFilter, I belive to solve it It's better create a custom implementation of whaterver class that implements OncePerRequestFilter, in my particular case I created an implementation of AuthenticationFilter.

Upvotes: 1

Ihor M.
Ihor M.

Reputation: 3148

I am seeing exactly the same behavior and I think it is related to the fact that asynchronous call is being split into 2 phases.

At first, regular container thread is kicked and an interim response is generated, but that response is not being returned to the client it is being held back until async dispatcher competes. Once async thread is done processing interim response is replaced with the real one from async thread and returned to the client.

Both threads go through the same filter chain. Therefore you see duplicate invocation.

If you want your filter to be invoked once you should extend from OncePerRequestFilter. It will check if your filter was already invoked during the course of the request (even though the request handling consists of 2 stages each of them handled by their own threads).

Upvotes: 4

Related Questions