Skip to content

getHandlerInternal support multiple calls and avoid repeated lookupHandlerMethod #29544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

ShijunDeng
Copy link

@ShijunDeng ShijunDeng commented Nov 22, 2022

In some scenarios, we need to get HandlerMethod ahead of org.springframework.web.reactive.DispatcherHandler, such as an implement of authentication by WebFilter

public class AuthFilter implements WebFilter, Ordered {

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return handlerMapping.getHandler(exchange).switchIfEmpty(chain.filter(exchange))
            .flatMap(handler -> {
                    if (handler instanceof HandlerMethod) {
                        HandlerMethod methodHandle = (HandlerMethod) handler;
                        CheckPermission permission = methodHandle.getMethodAnnotation(CheckPermission.class);
                        if (Objects.isNull(permission)) {
                            permission = AnnotationUtils.findAnnotation(methodHandle.getBeanType(), CheckPermission.class);
                        }

                        if (Objects.nonNull(permission)) {
                            // TODO  do something..
                        }
                    }
                    return chain.filter(exchange);
                }
            );
    }
}

HandlerMethod is necessary but there is no alternative way to get it withon WebFilter, which limited the capabilities of WebFilter. so, we need call getHandler, however this may lead to repeated call of lookupHandlerMethod and unexpected execution of exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); as below:

public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {

To avoid duplicate search for HandlerMethod in mapping.getHandler , I suggest implementing a improved getHandlerInternal, in which HandlerMethod would be keep in attributes as long as it found.

	@Override
	public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
		return Mono.justOrEmpty(exchange.<HandlerMethod>getAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE))
			.switchIfEmpty(Mono.defer(() -> getHandlerAndCache(exchange)));
	}

	protected Mono<HandlerMethod> getHandlerAndCache(ServerWebExchange exchange) {
		exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
		return super.getHandlerInternal(exchange)
			.doOnNext(handler -> exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handler))
			.doOnTerminate(() -> ProducesRequestCondition.clearMediaTypesAttribute(exchange));
	}

related issue:#20123

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 22, 2022
@ShijunDeng ShijunDeng closed this Nov 27, 2022
@ShijunDeng ShijunDeng deleted the RequestMappingInfoHandlerMapping branch November 27, 2022 09:27
@bclozel bclozel added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants