All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.security.web.util.matcher.MediaTypeRequestMatcher Maven / Gradle / Ivy

There is a newer version: 6.2.4
Show newest version
/*
 * Copyright 2002-2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.security.web.util.matcher;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.context.request.ServletWebRequest;

/**
 * Allows matching {@link HttpServletRequest} based upon the {@link MediaType}'s resolved
 * from a {@link ContentNegotiationStrategy}.
 *
 * By default, the matching process will perform the following:
 *
 * 
    *
  • The {@link ContentNegotiationStrategy} will resolve the {@link MediaType} 's for * the current request
  • *
  • Each matchingMediaTypes that was passed into the constructor will be compared * against the {@link MediaType} instances resolved from the * {@link ContentNegotiationStrategy}.
  • *
  • If one of the matchingMediaTypes is compatible with one of the resolved * {@link MediaType} returned from the {@link ContentNegotiationStrategy}, then it returns * true
  • *
* * For example, consider the following example * *
 * GET /
 * Accept: application/json
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * assert matcher.matches(request) == true // returns true
 * 
* * The following will also return true * *
 * GET /
 * Accept: */*
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * assert matcher.matches(request) == true // returns true
 * 
* *

Ignoring Media Types

* * Sometimes you may want to ignore certain types of media types. For example, you may * want to match on "application/json" but ignore "*/" sent by a web browser. * *
 * GET /
 * Accept: */*
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * matcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
 * assert matcher.matches(request) == false // returns false
 * 
* *
 * GET /
 * Accept: application/json
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * matcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
 * assert matcher.matches(request) == true // returns true
 * 
* *

Exact media type comparison

* * By default as long as the {@link MediaType} discovered by * {@link ContentNegotiationStrategy} returns true for * {@link MediaType#isCompatibleWith(MediaType)} on the matchingMediaTypes, the result of * the match is true. However, sometimes you may want to perform an exact match. This can * be done with the following examples: * *
 * GET /
 * Accept: application/json
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * matcher.setUseEquals(true);
 * assert matcher.matches(request) == true // returns true
 * 
* *
 * GET /
 * Accept: application/*
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * matcher.setUseEquals(true);
 * assert matcher.matches(request) == false // returns false
 * 
* *
 * GET /
 * Accept: */*
 *
 * ContentNegotiationStrategy negotiationStrategy = new HeaderContentNegotiationStrategy()
 * MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(negotiationStrategy, MediaType.APPLICATION_JSON);
 * matcher.setUseEquals(true);
 * assert matcher.matches(request) == false // returns false
 * 
* * @author Rob Winch * @since 3.2 */ public final class MediaTypeRequestMatcher implements RequestMatcher { private final Log logger = LogFactory.getLog(getClass()); private final ContentNegotiationStrategy contentNegotiationStrategy; private final Collection matchingMediaTypes; private boolean useEquals; private Set ignoredMediaTypes = Collections.emptySet(); /** * Creates an instance * @param contentNegotiationStrategy the {@link ContentNegotiationStrategy} to use * @param matchingMediaTypes the {@link MediaType} that will make the * {@link RequestMatcher} return true */ public MediaTypeRequestMatcher(ContentNegotiationStrategy contentNegotiationStrategy, MediaType... matchingMediaTypes) { this(contentNegotiationStrategy, Arrays.asList(matchingMediaTypes)); } /** * Creates an instance * @param contentNegotiationStrategy the {@link ContentNegotiationStrategy} to use * @param matchingMediaTypes the {@link MediaType} that will make the * {@link RequestMatcher} return true */ public MediaTypeRequestMatcher(ContentNegotiationStrategy contentNegotiationStrategy, Collection matchingMediaTypes) { Assert.notNull(contentNegotiationStrategy, "ContentNegotiationStrategy cannot be null"); Assert.notEmpty(matchingMediaTypes, "matchingMediaTypes cannot be null or empty"); this.contentNegotiationStrategy = contentNegotiationStrategy; this.matchingMediaTypes = matchingMediaTypes; } public boolean matches(HttpServletRequest request) { List httpRequestMediaTypes; try { httpRequestMediaTypes = this.contentNegotiationStrategy .resolveMediaTypes(new ServletWebRequest(request)); } catch (HttpMediaTypeNotAcceptableException e) { this.logger.debug("Failed to parse MediaTypes, returning false", e); return false; } if (this.logger.isDebugEnabled()) { this.logger.debug("httpRequestMediaTypes=" + httpRequestMediaTypes); } for (MediaType httpRequestMediaType : httpRequestMediaTypes) { if (this.logger.isDebugEnabled()) { this.logger.debug("Processing " + httpRequestMediaType); } if (shouldIgnore(httpRequestMediaType)) { this.logger.debug("Ignoring"); continue; } if (this.useEquals) { boolean isEqualTo = this.matchingMediaTypes .contains(httpRequestMediaType); this.logger.debug("isEqualTo " + isEqualTo); return isEqualTo; } for (MediaType matchingMediaType : this.matchingMediaTypes) { boolean isCompatibleWith = matchingMediaType .isCompatibleWith(httpRequestMediaType); if (this.logger.isDebugEnabled()) { this.logger.debug(matchingMediaType + " .isCompatibleWith " + httpRequestMediaType + " = " + isCompatibleWith); } if (isCompatibleWith) { return true; } } } this.logger.debug("Did not match any media types"); return false; } private boolean shouldIgnore(MediaType httpRequestMediaType) { for (MediaType ignoredMediaType : this.ignoredMediaTypes) { if (httpRequestMediaType.includes(ignoredMediaType)) { return true; } } return false; } /** * If set to true, matches on exact {@link MediaType}, else uses * {@link MediaType#isCompatibleWith(MediaType)}. * * @param useEquals specify if equals comparison should be used. */ public void setUseEquals(boolean useEquals) { this.useEquals = useEquals; } /** * Set the {@link MediaType} to ignore from the {@link ContentNegotiationStrategy}. * This is useful if for example, you want to match on * {@link MediaType#APPLICATION_JSON} but want to ignore {@link MediaType#ALL}. * * @param ignoredMediaTypes the {@link MediaType}'s to ignore from the * {@link ContentNegotiationStrategy} */ public void setIgnoredMediaTypes(Set ignoredMediaTypes) { this.ignoredMediaTypes = ignoredMediaTypes; } @Override public String toString() { return "MediaTypeRequestMatcher [contentNegotiationStrategy=" + this.contentNegotiationStrategy + ", matchingMediaTypes=" + this.matchingMediaTypes + ", useEquals=" + this.useEquals + ", ignoredMediaTypes=" + this.ignoredMediaTypes + "]"; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy