2626import java .util .function .Function ;
2727import java .util .function .Predicate ;
2828
29+ import org .apache .commons .logging .Log ;
30+ import org .apache .commons .logging .LogFactory ;
2931import reactor .core .publisher .Flux ;
3032import reactor .core .publisher .Mono ;
3133
3234import org .springframework .http .HttpMethod ;
3335import org .springframework .http .MediaType ;
3436import org .springframework .http .server .reactive .ServerHttpRequest ;
3537import org .springframework .util .Assert ;
38+ import org .springframework .util .StringUtils ;
3639import org .springframework .web .reactive .function .BodyExtractor ;
3740import org .springframework .web .server .WebSession ;
3841import org .springframework .web .util .UriUtils ;
4851 */
4952public abstract class RequestPredicates {
5053
54+ private static final Log logger = LogFactory .getLog (RequestPredicates .class );
55+
5156 private static final PathPatternParser DEFAULT_PATTERN_PARSER = new PathPatternParser ();
5257
5358 /**
@@ -119,11 +124,21 @@ public static RequestPredicate headers(Predicate<ServerRequest.Headers> headersP
119124 public static RequestPredicate contentType (MediaType ... mediaTypes ) {
120125 Assert .notEmpty (mediaTypes , "'mediaTypes' must not be empty" );
121126 Set <MediaType > mediaTypeSet = new HashSet <>(Arrays .asList (mediaTypes ));
122- return headers (headers -> {
123- MediaType contentType = headers .contentType ().orElse (MediaType .APPLICATION_OCTET_STREAM );
124- return mediaTypeSet .stream ()
125- .anyMatch (mediaType -> mediaType .includes (contentType ));
127+ return headers (new Predicate <ServerRequest .Headers >() {
128+ @ Override
129+ public boolean test (ServerRequest .Headers headers ) {
130+ MediaType contentType =
131+ headers .contentType ().orElse (MediaType .APPLICATION_OCTET_STREAM );
132+ boolean match = mediaTypeSet .stream ()
133+ .anyMatch (mediaType -> mediaType .includes (contentType ));
134+ traceMatch ("Content-Type" , mediaTypeSet , contentType , match );
135+ return match ;
136+ }
126137
138+ @ Override
139+ public String toString () {
140+ return String .format ("Content-Type: %s" , mediaTypeSet );
141+ }
127142 });
128143 }
129144
@@ -138,12 +153,23 @@ public static RequestPredicate contentType(MediaType... mediaTypes) {
138153 public static RequestPredicate accept (MediaType ... mediaTypes ) {
139154 Assert .notEmpty (mediaTypes , "'mediaTypes' must not be empty" );
140155 Set <MediaType > mediaTypeSet = new HashSet <>(Arrays .asList (mediaTypes ));
141- return headers (headers -> {
142- List <MediaType > acceptedMediaTypes = headers .accept ();
143- MediaType .sortBySpecificityAndQuality (acceptedMediaTypes );
144- return acceptedMediaTypes .stream ()
145- .anyMatch (acceptedMediaType -> mediaTypeSet .stream ()
146- .anyMatch (acceptedMediaType ::isCompatibleWith ));
156+ return headers (new Predicate <ServerRequest .Headers >() {
157+ @ Override
158+ public boolean test (ServerRequest .Headers headers ) {
159+ List <MediaType > acceptedMediaTypes = headers .accept ();
160+ MediaType .sortBySpecificityAndQuality (acceptedMediaTypes );
161+ boolean match = acceptedMediaTypes .stream ()
162+ .anyMatch (acceptedMediaType -> mediaTypeSet .stream ()
163+ .anyMatch (acceptedMediaType ::isCompatibleWith ));
164+ traceMatch ("Accept" , mediaTypeSet , acceptedMediaTypes , match );
165+ return match ;
166+ }
167+
168+ @ Override
169+ public String toString () {
170+ return String .format ("Accept: %s" , mediaTypeSet );
171+ }
172+
147173 });
148174 }
149175
@@ -238,7 +264,11 @@ public static RequestPredicate OPTIONS(String pattern) {
238264 */
239265 public static RequestPredicate pathExtension (String extension ) {
240266 Assert .notNull (extension , "'extension' must not be null" );
241- return pathExtension (extension ::equalsIgnoreCase );
267+ return pathExtension (pathExtension -> {
268+ boolean match = extension .equalsIgnoreCase (pathExtension );
269+ traceMatch ("Extension" , extension , pathExtension , match );
270+ return match ;
271+ });
242272 }
243273
244274 /**
@@ -289,6 +319,14 @@ public static RequestPredicate queryParam(String name, Predicate<String> predica
289319 };
290320 }
291321
322+ private static void traceMatch (String prefix , Object desired , Object actual , boolean match ) {
323+ if (logger .isTraceEnabled ()) {
324+ String message = String .format ("%s \" %s\" %s against value \" %s\" " ,
325+ prefix , desired , match ? "matches" : "does not match" , actual );
326+ logger .trace (message );
327+ }
328+ }
329+
292330
293331 private static class HttpMethodPredicate implements RequestPredicate {
294332
@@ -301,7 +339,14 @@ public HttpMethodPredicate(HttpMethod httpMethod) {
301339
302340 @ Override
303341 public boolean test (ServerRequest request ) {
304- return this .httpMethod == request .method ();
342+ boolean match = this .httpMethod == request .method ();
343+ traceMatch ("Method" , this .httpMethod , request .method (), match );
344+ return match ;
345+ }
346+
347+ @ Override
348+ public String toString () {
349+ return this .httpMethod .toString ();
305350 }
306351 }
307352
@@ -317,12 +362,11 @@ public PathPatternPredicate(PathPattern pattern) {
317362 @ Override
318363 public boolean test (ServerRequest request ) {
319364 String path = request .path ();
320- if (this .pattern .matches (path )) {
321- if (request instanceof DefaultServerRequest ) {
322- DefaultServerRequest defaultRequest = (DefaultServerRequest ) request ;
323- Map <String , String > uriTemplateVariables = this .pattern .matchAndExtract (path );
324- defaultRequest .exchange ().getAttributes ().put (RouterFunctions .URI_TEMPLATE_VARIABLES_ATTRIBUTE , uriTemplateVariables );
325- }
365+ boolean match = this .pattern .matches (path );
366+ traceMatch ("Pattern" , this .pattern .getPatternString (), path , match );
367+ if (match ) {
368+ Map <String , String > uriTemplateVariables = this .pattern .matchAndExtract (path );
369+ request .attributes ().put (RouterFunctions .URI_TEMPLATE_VARIABLES_ATTRIBUTE , uriTemplateVariables );
326370 return true ;
327371 }
328372 else {
@@ -331,11 +375,19 @@ public boolean test(ServerRequest request) {
331375 }
332376
333377 @ Override
334- public ServerRequest subRequest (ServerRequest request ) {
378+ public ServerRequest nestRequest (ServerRequest request ) {
335379 String requestPath = request .path ();
336380 String subPath = this .pattern .extractPathWithinPattern (requestPath );
381+ if (!subPath .startsWith ("/" )) {
382+ subPath = "/" + subPath ;
383+ }
337384 return new SubPathServerRequestWrapper (request , subPath );
338385 }
386+
387+ @ Override
388+ public String toString () {
389+ return this .pattern .getPatternString ();
390+ }
339391 }
340392
341393 private static class HeadersPredicate implements RequestPredicate {
@@ -351,6 +403,11 @@ public HeadersPredicate(Predicate<ServerRequest.Headers> headersPredicate) {
351403 public boolean test (ServerRequest request ) {
352404 return this .headersPredicate .test (request .headers ());
353405 }
406+
407+ @ Override
408+ public String toString () {
409+ return this .headersPredicate .toString ();
410+ }
354411 }
355412
356413 private static class SubPathServerRequestWrapper implements ServerRequest {
@@ -409,6 +466,11 @@ public <T> Optional<T> attribute(String name) {
409466 return this .request .attribute (name );
410467 }
411468
469+ @ Override
470+ public Map <String , Object > attributes () {
471+ return this .request .attributes ();
472+ }
473+
412474 @ Override
413475 public Optional <String > queryParam (String name ) {
414476 return this .request .queryParam (name );
@@ -433,5 +495,11 @@ public Map<String, String> pathVariables() {
433495 public Mono <WebSession > session () {
434496 return this .request .session ();
435497 }
498+
499+ @ Override
500+ public String toString () {
501+ return String .format ("%s %s" , method (), path ());
502+ }
503+
436504 }
437505}
0 commit comments