4242import org .springframework .context .ApplicationContext ;
4343import org .springframework .core .annotation .MergedAnnotation ;
4444import org .springframework .core .annotation .MergedAnnotations ;
45+ import org .springframework .http .HttpMethod ;
4546import org .springframework .security .web .util .matcher .AntPathRequestMatcher ;
4647import org .springframework .security .web .util .matcher .OrRequestMatcher ;
4748import org .springframework .security .web .util .matcher .RequestMatcher ;
5657 *
5758 * @author Madhura Bhave
5859 * @author Phillip Webb
60+ * @author Chris Bono
5961 * @since 2.0.0
6062 */
6163public final class EndpointRequest {
@@ -212,16 +214,21 @@ protected abstract RequestMatcher createDelegate(WebApplicationContext context,
212214
213215 protected final List <RequestMatcher > getDelegateMatchers (RequestMatcherFactory requestMatcherFactory ,
214216 RequestMatcherProvider matcherProvider , Set <String > paths ) {
217+ return getDelegateMatchers (requestMatcherFactory , matcherProvider , paths , null );
218+ }
219+
220+ protected final List <RequestMatcher > getDelegateMatchers (RequestMatcherFactory requestMatcherFactory ,
221+ RequestMatcherProvider matcherProvider , Set <String > paths , HttpMethod httpMethod ) {
215222 return paths .stream ()
216- .map ((path ) -> requestMatcherFactory .antPath (matcherProvider , path , "/**" ))
223+ .map ((path ) -> requestMatcherFactory .antPath (matcherProvider , httpMethod , path , "/**" ))
217224 .collect (Collectors .toCollection (ArrayList ::new ));
218225 }
219226
220227 protected List <RequestMatcher > getLinksMatchers (RequestMatcherFactory requestMatcherFactory ,
221228 RequestMatcherProvider matcherProvider , String basePath ) {
222229 List <RequestMatcher > linksMatchers = new ArrayList <>();
223- linksMatchers .add (requestMatcherFactory .antPath (matcherProvider , basePath ));
224- linksMatchers .add (requestMatcherFactory .antPath (matcherProvider , basePath , "/" ));
230+ linksMatchers .add (requestMatcherFactory .antPath (matcherProvider , null , basePath ));
231+ linksMatchers .add (requestMatcherFactory .antPath (matcherProvider , null , basePath , "/" ));
225232 return linksMatchers ;
226233 }
227234
@@ -230,7 +237,7 @@ protected RequestMatcherProvider getRequestMatcherProvider(WebApplicationContext
230237 return context .getBean (RequestMatcherProvider .class );
231238 }
232239 catch (NoSuchBeanDefinitionException ex ) {
233- return AntPathRequestMatcher :: new ;
240+ return ( pattern , method ) -> new AntPathRequestMatcher ( pattern , ( method != null ) ? method . name () : null ) ;
234241 }
235242 }
236243
@@ -273,38 +280,52 @@ public static final class EndpointRequestMatcher extends AbstractRequestMatcher
273280
274281 private final boolean includeLinks ;
275282
283+ private final HttpMethod httpMethod ;
284+
276285 private EndpointRequestMatcher (boolean includeLinks ) {
277- this (Collections .emptyList (), Collections .emptyList (), includeLinks );
286+ this (Collections .emptyList (), Collections .emptyList (), includeLinks , null );
278287 }
279288
280289 private EndpointRequestMatcher (Class <?>[] endpoints , boolean includeLinks ) {
281- this (Arrays .asList ((Object []) endpoints ), Collections .emptyList (), includeLinks );
290+ this (Arrays .asList ((Object []) endpoints ), Collections .emptyList (), includeLinks , null );
282291 }
283292
284293 private EndpointRequestMatcher (String [] endpoints , boolean includeLinks ) {
285- this (Arrays .asList ((Object []) endpoints ), Collections .emptyList (), includeLinks );
294+ this (Arrays .asList ((Object []) endpoints ), Collections .emptyList (), includeLinks , null );
286295 }
287296
288- private EndpointRequestMatcher (List <Object > includes , List <Object > excludes , boolean includeLinks ) {
297+ private EndpointRequestMatcher (List <Object > includes , List <Object > excludes , boolean includeLinks ,
298+ HttpMethod httpMethod ) {
289299 this .includes = includes ;
290300 this .excludes = excludes ;
291301 this .includeLinks = includeLinks ;
302+ this .httpMethod = httpMethod ;
292303 }
293304
294305 public EndpointRequestMatcher excluding (Class <?>... endpoints ) {
295306 List <Object > excludes = new ArrayList <>(this .excludes );
296307 excludes .addAll (Arrays .asList ((Object []) endpoints ));
297- return new EndpointRequestMatcher (this .includes , excludes , this .includeLinks );
308+ return new EndpointRequestMatcher (this .includes , excludes , this .includeLinks , null );
298309 }
299310
300311 public EndpointRequestMatcher excluding (String ... endpoints ) {
301312 List <Object > excludes = new ArrayList <>(this .excludes );
302313 excludes .addAll (Arrays .asList ((Object []) endpoints ));
303- return new EndpointRequestMatcher (this .includes , excludes , this .includeLinks );
314+ return new EndpointRequestMatcher (this .includes , excludes , this .includeLinks , null );
304315 }
305316
306317 public EndpointRequestMatcher excludingLinks () {
307- return new EndpointRequestMatcher (this .includes , this .excludes , false );
318+ return new EndpointRequestMatcher (this .includes , this .excludes , false , null );
319+ }
320+
321+ /**
322+ * Restricts the matcher to only consider requests with a particular http method.
323+ * @param httpMethod the http method to include
324+ * @return a copy of the matcher further restricted to only match requests with
325+ * the specified http method
326+ */
327+ public EndpointRequestMatcher withHttpMethod (HttpMethod httpMethod ) {
328+ return new EndpointRequestMatcher (this .includes , this .excludes , false , httpMethod );
308329 }
309330
310331 @ Override
@@ -318,7 +339,8 @@ protected RequestMatcher createDelegate(WebApplicationContext context,
318339 }
319340 streamPaths (this .includes , endpoints ).forEach (paths ::add );
320341 streamPaths (this .excludes , endpoints ).forEach (paths ::remove );
321- List <RequestMatcher > delegateMatchers = getDelegateMatchers (requestMatcherFactory , matcherProvider , paths );
342+ List <RequestMatcher > delegateMatchers = getDelegateMatchers (requestMatcherFactory , matcherProvider , paths ,
343+ this .httpMethod );
322344 String basePath = endpoints .getBasePath ();
323345 if (this .includeLinks && StringUtils .hasText (basePath )) {
324346 delegateMatchers .addAll (getLinksMatchers (requestMatcherFactory , matcherProvider , basePath ));
@@ -426,12 +448,12 @@ public String toString() {
426448 */
427449 private static final class RequestMatcherFactory {
428450
429- RequestMatcher antPath (RequestMatcherProvider matcherProvider , String ... parts ) {
451+ RequestMatcher antPath (RequestMatcherProvider matcherProvider , HttpMethod httpMethod , String ... parts ) {
430452 StringBuilder pattern = new StringBuilder ();
431453 for (String part : parts ) {
432454 pattern .append (part );
433455 }
434- return matcherProvider .getRequestMatcher (pattern .toString ());
456+ return matcherProvider .getRequestMatcher (pattern .toString (), httpMethod );
435457 }
436458
437459 }
0 commit comments