001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.function; 018 019import java.util.function.BiFunction; 020import java.util.function.Function; 021import java.util.function.Predicate; 022 023import org.springframework.util.Assert; 024 025/** 026 * Represents a function that filters a {@linkplain HandlerFunction handler function}. 027 * 028 * @author Arjen Poutsma 029 * @since 5.2 030 * @param <T> the type of the {@linkplain HandlerFunction handler function} to filter 031 * @param <R> the type of the response of the function 032 * @see RouterFunction#filter(HandlerFilterFunction) 033 */ 034@FunctionalInterface 035public interface HandlerFilterFunction<T extends ServerResponse, R extends ServerResponse> { 036 037 /** 038 * Apply this filter to the given handler function. The given 039 * {@linkplain HandlerFunction handler function} represents the next entity in the chain, 040 * and can be {@linkplain HandlerFunction#handle(ServerRequest) invoked} in order to 041 * proceed to this entity, or not invoked to block the chain. 042 * @param request the request 043 * @param next the next handler or filter function in the chain 044 * @return the filtered response 045 */ 046 R filter(ServerRequest request, HandlerFunction<T> next) throws Exception; 047 048 /** 049 * Return a composed filter function that first applies this filter, and then applies the 050 * {@code after} filter. 051 * @param after the filter to apply after this filter is applied 052 * @return a composed filter that first applies this function and then applies the 053 * {@code after} function 054 */ 055 default HandlerFilterFunction<T, R> andThen(HandlerFilterFunction<T, T> after) { 056 Assert.notNull(after, "HandlerFilterFunction must not be null"); 057 return (request, next) -> { 058 HandlerFunction<T> nextHandler = handlerRequest -> after.filter(handlerRequest, next); 059 return filter(request, nextHandler); 060 }; 061 } 062 063 /** 064 * Apply this filter to the given handler function, resulting in a filtered handler function. 065 * @param handler the handler function to filter 066 * @return the filtered handler function 067 */ 068 default HandlerFunction<R> apply(HandlerFunction<T> handler) { 069 Assert.notNull(handler, "HandlerFunction must not be null"); 070 return request -> this.filter(request, handler); 071 } 072 073 /** 074 * Adapt the given request processor function to a filter function that only operates 075 * on the {@code ServerRequest}. 076 * @param requestProcessor the request processor 077 * @return the filter adaptation of the request processor 078 */ 079 static <T extends ServerResponse> HandlerFilterFunction<T, T> 080 ofRequestProcessor(Function<ServerRequest, ServerRequest> requestProcessor) { 081 082 Assert.notNull(requestProcessor, "Function must not be null"); 083 return (request, next) -> next.handle(requestProcessor.apply(request)); 084 } 085 086 /** 087 * Adapt the given response processor function to a filter function that only operates 088 * on the {@code ServerResponse}. 089 * @param responseProcessor the response processor 090 * @return the filter adaptation of the request processor 091 */ 092 static <T extends ServerResponse, R extends ServerResponse> HandlerFilterFunction<T, R> 093 ofResponseProcessor(BiFunction<ServerRequest, T, R> responseProcessor) { 094 095 Assert.notNull(responseProcessor, "Function must not be null"); 096 return (request, next) -> responseProcessor.apply(request, next.handle(request)); 097 } 098 099 /** 100 * Adapt the given predicate and response provider function to a filter function that returns 101 * a {@code ServerResponse} on a given exception. 102 * @param predicate the predicate to match an exception 103 * @param errorHandler the response provider 104 * @return the filter adaption of the error handler 105 */ 106 static <T extends ServerResponse> HandlerFilterFunction<T, T> 107 ofErrorHandler(Predicate<Throwable> predicate, BiFunction<Throwable, ServerRequest, T> errorHandler) { 108 109 Assert.notNull(predicate, "Predicate must not be null"); 110 Assert.notNull(errorHandler, "ErrorHandler must not be null"); 111 112 return (request, next) -> { 113 try { 114 T t = next.handle(request); 115 if (t instanceof DefaultServerResponseBuilder.AbstractServerResponse) { 116 ((DefaultServerResponseBuilder.AbstractServerResponse) t) 117 .addErrorHandler(predicate, errorHandler); 118 } 119 return t; 120 } 121 catch (Throwable throwable) { 122 if (predicate.test(throwable)) { 123 return errorHandler.apply(throwable, request); 124 } 125 else { 126 throw throwable; 127 } 128 } 129 }; 130 } 131 132}