19
19
import java .io .IOException ;
20
20
import java .util .ArrayList ;
21
21
import java .util .Collections ;
22
+ import java .util .Enumeration ;
23
+ import java .util .HashMap ;
22
24
import java .util .List ;
23
25
import java .util .Map ;
24
26
import java .util .Properties ;
@@ -138,16 +140,17 @@ public void afterPropertiesSet() {
138
140
*/
139
141
@ Nullable
140
142
public MatchableHandlerMapping getMatchableHandlerMapping (HttpServletRequest request ) throws Exception {
141
- HttpServletRequest wrappedRequest = new RequestAttributeChangeIgnoringWrapper (request );
143
+ HttpServletRequest wrappedRequest = new AttributesPreservingRequest (request );
142
144
return doWithMatchingMapping (wrappedRequest , false , (matchedMapping , executionChain ) -> {
143
145
if (matchedMapping instanceof MatchableHandlerMapping ) {
144
146
PathPatternMatchableHandlerMapping mapping = this .pathPatternHandlerMappings .get (matchedMapping );
145
147
if (mapping != null ) {
146
- RequestPath requestPath = ServletRequestPathUtils .getParsedRequestPath (request );
147
- return mapping . decorate ( requestPath );
148
+ RequestPath requestPath = ServletRequestPathUtils .getParsedRequestPath (wrappedRequest );
149
+ return new PathSettingHandlerMapping ( mapping , requestPath );
148
150
}
149
151
else {
150
- return (MatchableHandlerMapping ) matchedMapping ;
152
+ String lookupPath = (String ) wrappedRequest .getAttribute (UrlPathHelper .PATH_ATTRIBUTE );
153
+ return new PathSettingHandlerMapping ((MatchableHandlerMapping ) matchedMapping , lookupPath );
151
154
}
152
155
}
153
156
throw new IllegalStateException ("HandlerMapping is not a MatchableHandlerMapping" );
@@ -157,7 +160,7 @@ public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest req
157
160
@ Override
158
161
@ Nullable
159
162
public CorsConfiguration getCorsConfiguration (HttpServletRequest request ) {
160
- RequestAttributeChangeIgnoringWrapper wrappedRequest = new RequestAttributeChangeIgnoringWrapper (request );
163
+ AttributesPreservingRequest wrappedRequest = new AttributesPreservingRequest (request );
161
164
return doWithMatchingMappingIgnoringException (wrappedRequest , (handlerMapping , executionChain ) -> {
162
165
for (HandlerInterceptor interceptor : executionChain .getInterceptorList ()) {
163
166
if (interceptor instanceof CorsConfigurationSource ) {
@@ -272,19 +275,83 @@ private static Map<HandlerMapping, PathPatternMatchableHandlerMapping> initPathP
272
275
273
276
274
277
/**
275
- * Request wrapper that ignores request attribute changes.
278
+ * Request wrapper that buffers request attributes in order protect the
279
+ * underlying request from attribute changes.
276
280
*/
277
- private static class RequestAttributeChangeIgnoringWrapper extends HttpServletRequestWrapper {
281
+ private static class AttributesPreservingRequest extends HttpServletRequestWrapper {
278
282
279
- RequestAttributeChangeIgnoringWrapper (HttpServletRequest request ) {
283
+ private final Map <String , Object > attributes ;
284
+
285
+ AttributesPreservingRequest (HttpServletRequest request ) {
280
286
super (request );
287
+ this .attributes = initAttributes (request );
288
+ }
289
+
290
+ private Map <String , Object > initAttributes (HttpServletRequest request ) {
291
+ Map <String , Object > map = new HashMap <>();
292
+ Enumeration <String > names = request .getAttributeNames ();
293
+ while (names .hasMoreElements ()) {
294
+ String name = names .nextElement ();
295
+ map .put (name , request .getAttribute (name ));
296
+ }
297
+ return map ;
281
298
}
282
299
283
300
@ Override
284
301
public void setAttribute (String name , Object value ) {
285
- if (name .equals (ServletRequestPathUtils .PATH_ATTRIBUTE ) || name .equals (UrlPathHelper .PATH_ATTRIBUTE )) {
286
- super .setAttribute (name , value );
302
+ this .attributes .put (name , value );
303
+ }
304
+
305
+ @ Override
306
+ public Object getAttribute (String name ) {
307
+ return this .attributes .get (name );
308
+ }
309
+
310
+ @ Override
311
+ public Enumeration <String > getAttributeNames () {
312
+ return Collections .enumeration (this .attributes .keySet ());
313
+ }
314
+
315
+ @ Override
316
+ public void removeAttribute (String name ) {
317
+ this .attributes .remove (name );
318
+ }
319
+ }
320
+
321
+
322
+ private static class PathSettingHandlerMapping implements MatchableHandlerMapping {
323
+
324
+ private final MatchableHandlerMapping delegate ;
325
+
326
+ private final Object path ;
327
+
328
+ private final String pathAttributeName ;
329
+
330
+ PathSettingHandlerMapping (MatchableHandlerMapping delegate , Object path ) {
331
+ this .delegate = delegate ;
332
+ this .path = path ;
333
+ this .pathAttributeName = (path instanceof RequestPath ?
334
+ ServletRequestPathUtils .PATH_ATTRIBUTE : UrlPathHelper .PATH_ATTRIBUTE );
335
+ }
336
+
337
+ @ Nullable
338
+ @ Override
339
+ public RequestMatchResult match (HttpServletRequest request , String pattern ) {
340
+ Object previousPath = request .getAttribute (this .pathAttributeName );
341
+ request .setAttribute (this .pathAttributeName , this .path );
342
+ try {
343
+ return this .delegate .match (request , pattern );
344
+ }
345
+ finally {
346
+ request .setAttribute (this .pathAttributeName , previousPath );
287
347
}
288
348
}
349
+
350
+ @ Nullable
351
+ @ Override
352
+ public HandlerExecutionChain getHandler (HttpServletRequest request ) throws Exception {
353
+ return this .delegate .getHandler (request );
354
+ }
289
355
}
356
+
290
357
}
0 commit comments