22
22
import jakarta .servlet .http .HttpServletResponse ;
23
23
import org .jspecify .annotations .Nullable ;
24
24
25
+ import org .springframework .http .HttpMethod ;
25
26
import org .springframework .http .server .PathContainer ;
26
27
import org .springframework .util .AntPathMatcher ;
27
28
import org .springframework .util .ObjectUtils ;
@@ -67,6 +68,10 @@ public final class MappedInterceptor implements HandlerInterceptor {
67
68
68
69
private final PatternAdapter @ Nullable [] excludePatterns ;
69
70
71
+ private final MethodAdapter @ Nullable [] includeHttpMethods ;
72
+
73
+ private final MethodAdapter @ Nullable [] excludeHttpMethods ;
74
+
70
75
private PathMatcher pathMatcher = defaultPathMatcher ;
71
76
72
77
private final HandlerInterceptor interceptor ;
@@ -78,58 +83,79 @@ public final class MappedInterceptor implements HandlerInterceptor {
78
83
* @param includePatterns patterns to which requests must match, or null to
79
84
* match all paths
80
85
* @param excludePatterns patterns to which requests must not match
86
+ * @param includeHttpMethods http methods to which request must match, or null to match all paths
87
+ * @param excludeHttpMethods http methods to which request must not match
81
88
* @param interceptor the target interceptor
82
89
* @param parser a parser to use to pre-parse patterns into {@link PathPattern};
83
90
* when not provided, {@link PathPatternParser#defaultInstance} is used.
84
91
* @since 5.3
85
92
*/
86
- public MappedInterceptor (String @ Nullable [] includePatterns , String @ Nullable [] excludePatterns ,
93
+ public MappedInterceptor (String @ Nullable [] includePatterns , String @ Nullable [] excludePatterns , HttpMethod @ Nullable [] includeHttpMethods , HttpMethod @ Nullable [] excludeHttpMethods ,
87
94
HandlerInterceptor interceptor , @ Nullable PathPatternParser parser ) {
88
95
89
96
this .includePatterns = PatternAdapter .initPatterns (includePatterns , parser );
90
97
this .excludePatterns = PatternAdapter .initPatterns (excludePatterns , parser );
98
+ this .includeHttpMethods = MethodAdapter .initHttpMethods (includeHttpMethods );
99
+ this .excludeHttpMethods = MethodAdapter .initHttpMethods (excludeHttpMethods );
91
100
this .interceptor = interceptor ;
92
101
}
93
102
94
103
95
104
/**
96
105
* Variant of
97
- * {@link #MappedInterceptor(String[], String[], HandlerInterceptor, PathPatternParser)}
106
+ * {@link #MappedInterceptor(String[], String[], HttpMethod[], HttpMethod[], HandlerInterceptor, PathPatternParser)}
98
107
* with include patterns only.
99
108
*/
100
109
public MappedInterceptor (String @ Nullable [] includePatterns , HandlerInterceptor interceptor ) {
101
- this (includePatterns , null , interceptor );
110
+ this (includePatterns , null , null , null , interceptor );
102
111
}
103
112
104
113
/**
105
114
* Variant of
106
- * {@link #MappedInterceptor(String[], String[], HandlerInterceptor, PathPatternParser)}
115
+ * {@link #MappedInterceptor(String[], String[], HttpMethod[], HttpMethod[], HandlerInterceptor, PathPatternParser)}
116
+ * with include methods only.
117
+ */
118
+ public MappedInterceptor (HttpMethod @ Nullable [] includeHttpMethods , HandlerInterceptor interceptor ) {
119
+ this (null , null , includeHttpMethods , null , interceptor );
120
+ }
121
+
122
+ /**
123
+ * Variant of
124
+ * {@link #MappedInterceptor(String[], String[], HttpMethod[], HttpMethod[], HandlerInterceptor, PathPatternParser)}
107
125
* without a provided parser.
108
126
*/
109
- public MappedInterceptor (String @ Nullable [] includePatterns , String @ Nullable [] excludePatterns ,
127
+ public MappedInterceptor (String @ Nullable [] includePatterns , String @ Nullable [] excludePatterns , HttpMethod @ Nullable [] includeHttpMethods , HttpMethod @ Nullable [] excludeHttpMethods ,
110
128
HandlerInterceptor interceptor ) {
111
129
112
- this (includePatterns , excludePatterns , interceptor , null );
130
+ this (includePatterns , excludePatterns ,includeHttpMethods , excludeHttpMethods , interceptor , null );
113
131
}
114
132
115
133
/**
116
134
* Variant of
117
- * {@link #MappedInterceptor(String[], String[], HandlerInterceptor, PathPatternParser)}
135
+ * {@link #MappedInterceptor(String[], String[], HttpMethod[], HttpMethod[], HandlerInterceptor, PathPatternParser)}
118
136
* with a {@link WebRequestInterceptor} as the target.
119
137
*/
120
138
public MappedInterceptor (String @ Nullable [] includePatterns , WebRequestInterceptor interceptor ) {
121
- this (includePatterns , null , interceptor );
139
+ this (includePatterns , null ,null ,null , interceptor );
140
+ }
141
+ /**
142
+ * Variant of
143
+ * {@link #MappedInterceptor(String[], String[], HttpMethod[], HttpMethod[], HandlerInterceptor, PathPatternParser)}
144
+ * with a {@link WebRequestInterceptor} as the target.
145
+ */
146
+ public MappedInterceptor (HttpMethod @ Nullable [] includeHttpMethods , WebRequestInterceptor interceptor ) {
147
+ this (null , null ,includeHttpMethods ,null , interceptor );
122
148
}
123
149
124
150
/**
125
151
* Variant of
126
- * {@link #MappedInterceptor(String[], String[], HandlerInterceptor, PathPatternParser)}
152
+ * {@link #MappedInterceptor(String[], String[], HttpMethod[], HttpMethod[] , HandlerInterceptor, PathPatternParser)}
127
153
* with a {@link WebRequestInterceptor} as the target.
128
154
*/
129
- public MappedInterceptor (String @ Nullable [] includePatterns , String @ Nullable [] excludePatterns ,
155
+ public MappedInterceptor (String @ Nullable [] includePatterns , String @ Nullable [] excludePatterns , HttpMethod @ Nullable [] includeHttpMethods , HttpMethod @ Nullable [] excludeHttpMethods ,
130
156
WebRequestInterceptor interceptor ) {
131
157
132
- this (includePatterns , excludePatterns , new WebRequestHandlerInterceptorAdapter (interceptor ));
158
+ this (includePatterns , excludePatterns ,includeHttpMethods , excludeHttpMethods , new WebRequestHandlerInterceptorAdapter (interceptor ));
133
159
}
134
160
135
161
@@ -202,6 +228,7 @@ public PathMatcher getPathMatcher() {
202
228
*/
203
229
public boolean matches (HttpServletRequest request ) {
204
230
Object path = ServletRequestPathUtils .getCachedPath (request );
231
+ HttpMethod method = HttpMethod .valueOf (request .getMethod ());
205
232
if (this .pathMatcher != defaultPathMatcher ) {
206
233
path = path .toString ();
207
234
}
@@ -213,12 +240,45 @@ public boolean matches(HttpServletRequest request) {
213
240
}
214
241
}
215
242
}
216
- if (ObjectUtils .isEmpty (this .includePatterns )) {
243
+ if (!ObjectUtils .isEmpty (this .excludeHttpMethods )) {
244
+ for (MethodAdapter adapter : this .excludeHttpMethods ) {
245
+ if (adapter .match (method )){
246
+ return false ;
247
+ }
248
+ }
249
+ }
250
+ if (ObjectUtils .isEmpty (this .includePatterns ) && ObjectUtils .isEmpty (this .includeHttpMethods )) {
217
251
return true ;
218
252
}
219
- for (PatternAdapter adapter : this .includePatterns ) {
220
- if (adapter .match (path , isPathContainer , this .pathMatcher )) {
221
- return true ;
253
+ if (!ObjectUtils .isEmpty (this .includePatterns ) && ObjectUtils .isEmpty (this .includeHttpMethods )) {
254
+ for (PatternAdapter adapter : this .includePatterns ) {
255
+ if (adapter .match (path , isPathContainer , this .pathMatcher )) {
256
+ return true ;
257
+ }
258
+ }
259
+ }
260
+ if (!ObjectUtils .isEmpty (this .includeHttpMethods ) && ObjectUtils .isEmpty (this .includePatterns )) {
261
+ for (MethodAdapter adapter : this .includeHttpMethods ) {
262
+ if (adapter .match (method )) {
263
+ return true ;
264
+ }
265
+ }
266
+ }
267
+ if (!ObjectUtils .isEmpty (this .includePatterns ) && !ObjectUtils .isEmpty (this .includeHttpMethods )) {
268
+ boolean match = false ;
269
+ for (MethodAdapter methodAdapter : this .includeHttpMethods ) {
270
+ if (methodAdapter .match (method )) {
271
+ match = true ;
272
+ break ;
273
+ }
274
+ }
275
+ if (!match ) {
276
+ return false ;
277
+ }
278
+ for (PatternAdapter pathAdapter : this .includePatterns ) {
279
+ if (pathAdapter .match (path , isPathContainer , pathMatcher )) {
280
+ return true ;
281
+ }
222
282
}
223
283
}
224
284
return false ;
@@ -305,4 +365,40 @@ public boolean match(Object path, boolean isPathContainer, PathMatcher pathMatch
305
365
}
306
366
}
307
367
368
+ /**
369
+ * Adapts {@link HttpMethod} instances for internal matching purposes.
370
+ *
371
+ * <p>Encapsulates an {@link HttpMethod} and provides matching functionality.
372
+ * Also provides a utility method to initialize arrays of {@code MethodAdapter}
373
+ * instances from arrays of {@link HttpMethod}.</p>
374
+ *
375
+ * @since 7.0.x
376
+ */
377
+ private static class MethodAdapter {
378
+
379
+ private final @ Nullable HttpMethod httpMethod ;
380
+
381
+ public MethodAdapter (@ Nullable HttpMethod httpMethod ) {
382
+ this .httpMethod = httpMethod ;
383
+ }
384
+
385
+ public boolean match (HttpMethod method ) {
386
+ return this .httpMethod == method ;
387
+ }
388
+
389
+ public @ Nullable HttpMethod getHttpMethod () {
390
+ return this .httpMethod ;
391
+ }
392
+
393
+ private static MethodAdapter @ Nullable [] initHttpMethods (HttpMethod @ Nullable [] methods ) {
394
+ if (ObjectUtils .isEmpty (methods )) {
395
+ return null ;
396
+ }
397
+ return Arrays .stream (methods )
398
+ .map (MethodAdapter ::new )
399
+ .toArray (MethodAdapter []::new );
400
+ }
401
+
402
+ }
403
+
308
404
}
0 commit comments