Remove JSONP support
CORS is now widely supported and should be used instead for cross-domain requests. Issue: SPR-16914
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A convenient base class for a {@code ResponseBodyAdvice} to instruct the
|
||||
* {@link org.springframework.http.converter.json.MappingJackson2HttpMessageConverter}
|
||||
* to serialize with JSONP formatting.
|
||||
*
|
||||
* <p>Sub-classes must specify the query parameter name(s) to check for the name
|
||||
* of the JSONP callback function.
|
||||
*
|
||||
* <p>Sub-classes are likely to be annotated with the {@code @ControllerAdvice}
|
||||
* annotation and auto-detected or otherwise must be registered directly with the
|
||||
* {@code RequestMappingHandlerAdapter} and {@code ExceptionHandlerExceptionResolver}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class AbstractJsonpResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {
|
||||
|
||||
/**
|
||||
* Pattern for validating jsonp callback parameter values.
|
||||
*/
|
||||
private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
|
||||
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final String[] jsonpQueryParamNames;
|
||||
|
||||
|
||||
protected AbstractJsonpResponseBodyAdvice(String... queryParamNames) {
|
||||
Assert.isTrue(!ObjectUtils.isEmpty(queryParamNames), "At least one query param name is required");
|
||||
this.jsonpQueryParamNames = queryParamNames;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType,
|
||||
MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
|
||||
|
||||
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
|
||||
for (String name : this.jsonpQueryParamNames) {
|
||||
String value = servletRequest.getParameter(name);
|
||||
if (value != null) {
|
||||
if (!isValidJsonpQueryParam(value)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring invalid jsonp parameter value: " + value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
MediaType contentTypeToUse = getContentType(contentType, request, response);
|
||||
response.getHeaders().setContentType(contentTypeToUse);
|
||||
bodyContainer.setJsonpFunction(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the jsonp query parameter value. The default implementation
|
||||
* returns true if it consists of digits, letters, or "_" and ".".
|
||||
* Invalid parameter values are ignored.
|
||||
* @param value the query param value, never {@code null}
|
||||
* @since 4.1.8
|
||||
*/
|
||||
protected boolean isValidJsonpQueryParam(String value) {
|
||||
return CALLBACK_PARAM_PATTERN.matcher(value).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content type to set the response to.
|
||||
* This implementation always returns "application/javascript".
|
||||
* @param contentType the content type selected through content negotiation
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
* @return the content type to set the response to
|
||||
*/
|
||||
protected MediaType getContentType(MediaType contentType, ServerHttpRequest request, ServerHttpResponse response) {
|
||||
return new MediaType("application", "javascript");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -17,15 +17,10 @@
|
||||
package org.springframework.web.servlet.view.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -33,10 +28,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ser.FilterProvider;
|
||||
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
@@ -67,17 +60,6 @@ public class MappingJackson2JsonView extends AbstractJackson2View {
|
||||
*/
|
||||
public static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
|
||||
/**
|
||||
* Default content type for JSONP: "application/javascript".
|
||||
*/
|
||||
public static final String DEFAULT_JSONP_CONTENT_TYPE = "application/javascript";
|
||||
|
||||
/**
|
||||
* Pattern for validating jsonp callback parameter values.
|
||||
*/
|
||||
private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*");
|
||||
|
||||
|
||||
@Nullable
|
||||
private String jsonPrefix;
|
||||
|
||||
@@ -86,9 +68,6 @@ public class MappingJackson2JsonView extends AbstractJackson2View {
|
||||
|
||||
private boolean extractValueFromSingleKeyModel = false;
|
||||
|
||||
@Nullable
|
||||
private Set<String> jsonpParameterNames = new LinkedHashSet<>(Arrays.asList("jsonp", "callback"));
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new {@code MappingJackson2JsonView} using default configuration
|
||||
@@ -166,49 +145,6 @@ public class MappingJackson2JsonView extends AbstractJackson2View {
|
||||
this.extractValueFromSingleKeyModel = extractValueFromSingleKeyModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set JSONP request parameter names. Each time a request has one of those
|
||||
* parameters, the resulting JSON will be wrapped into a function named as
|
||||
* specified by the JSONP request parameter value.
|
||||
* <p>The parameter names configured by default are "jsonp" and "callback".
|
||||
* @since 4.1
|
||||
* @see <a href="http://en.wikipedia.org/wiki/JSONP">JSONP Wikipedia article</a>
|
||||
*/
|
||||
public void setJsonpParameterNames(Set<String> jsonpParameterNames) {
|
||||
this.jsonpParameterNames = jsonpParameterNames;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getJsonpParameterValue(HttpServletRequest request) {
|
||||
if (this.jsonpParameterNames != null) {
|
||||
for (String name : this.jsonpParameterNames) {
|
||||
String value = request.getParameter(name);
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
if (!isValidJsonpQueryParam(value)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring invalid jsonp parameter value: " + value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the jsonp query parameter value. The default implementation
|
||||
* returns true if it consists of digits, letters, or "_" and ".".
|
||||
* Invalid parameter values are ignored.
|
||||
* @param value the query param value, never {@code null}
|
||||
* @since 4.1.8
|
||||
*/
|
||||
protected boolean isValidJsonpQueryParam(String value) {
|
||||
return CALLBACK_PARAM_PATTERN.matcher(value).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out undesired attributes from the given model.
|
||||
* The return value can be either another {@link Map} or a single value object.
|
||||
@@ -231,58 +167,11 @@ public class MappingJackson2JsonView extends AbstractJackson2View {
|
||||
return (this.extractValueFromSingleKeyModel && result.size() == 1 ? result.values().iterator().next() : result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object filterAndWrapModel(Map<String, Object> model, HttpServletRequest request) {
|
||||
Object value = super.filterAndWrapModel(model, request);
|
||||
String jsonpParameterValue = getJsonpParameterValue(request);
|
||||
if (jsonpParameterValue != null) {
|
||||
if (value instanceof MappingJacksonValue) {
|
||||
((MappingJacksonValue) value).setJsonpFunction(jsonpParameterValue);
|
||||
}
|
||||
else {
|
||||
MappingJacksonValue container = new MappingJacksonValue(value);
|
||||
container.setJsonpFunction(jsonpParameterValue);
|
||||
value = container;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
|
||||
if (this.jsonPrefix != null) {
|
||||
generator.writeRaw(this.jsonPrefix);
|
||||
}
|
||||
|
||||
String jsonpFunction = null;
|
||||
if (object instanceof MappingJacksonValue) {
|
||||
jsonpFunction = ((MappingJacksonValue) object).getJsonpFunction();
|
||||
}
|
||||
if (jsonpFunction != null) {
|
||||
generator.writeRaw("/**/");
|
||||
generator.writeRaw(jsonpFunction + "(");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {
|
||||
String jsonpFunction = null;
|
||||
if (object instanceof MappingJacksonValue) {
|
||||
jsonpFunction = ((MappingJacksonValue) object).getJsonpFunction();
|
||||
}
|
||||
if (jsonpFunction != null) {
|
||||
generator.writeRaw(");");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setResponseContentType(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (getJsonpParameterValue(request) != null) {
|
||||
response.setContentType(DEFAULT_JSONP_CONTENT_TYPE);
|
||||
}
|
||||
else {
|
||||
super.setResponseContentType(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user