From ac37b678a3ac9ee541a10e8ad74d612bb9ec5b88 Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Thu, 7 Jun 2018 11:33:25 +0200 Subject: [PATCH] Remove JSONP support CORS is now widely supported and should be used instead for cross-domain requests. Issue: SPR-16914 --- .../MappingJackson2HttpMessageConverter.java | 17 +-- .../converter/json/MappingJacksonValue.java | 20 +-- ...pingJackson2HttpMessageConverterTests.java | 33 ----- .../AbstractJsonpResponseBodyAdvice.java | 114 ------------------ .../view/json/MappingJackson2JsonView.java | 113 +---------------- .../RequestMappingHandlerAdapterTests.java | 29 +---- .../json/MappingJackson2JsonViewTests.java | 33 +---- .../StompWebSocketEndpointRegistration.java | 4 +- .../WebSocketHandlerRegistration.java | 4 +- .../sockjs/support/AbstractSockJsService.java | 6 +- .../sockjs/transport/TransportType.java | 6 +- .../AbstractHttpSendingTransportHandler.java | 4 +- .../handler/DefaultSockJsService.java | 4 +- .../handler/JsonpPollingTransportHandler.java | 102 ---------------- .../JsonpReceivingTransportHandler.java | 85 ------------- .../HandlersBeanDefinitionParserTests.java | 6 +- .../sockjs/transport/TransportTypeTests.java | 4 +- .../handler/DefaultSockJsServiceTests.java | 35 +----- .../HttpReceivingTransportHandlerTests.java | 33 +---- .../HttpSendingTransportHandlerTests.java | 53 +------- src/docs/asciidoc/web/webmvc-view.adoc | 5 - src/docs/asciidoc/web/webmvc.adoc | 24 ---- src/docs/asciidoc/web/websocket.adoc | 4 +- 23 files changed, 25 insertions(+), 713 deletions(-) delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java delete mode 100644 spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/JsonpPollingTransportHandler.java delete mode 100644 spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/handler/JsonpReceivingTransportHandler.java diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java index 4e54a23f5fa..0c31b2b6c6f 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java @@ -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. @@ -95,21 +95,6 @@ public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMes if (this.jsonPrefix != null) { generator.writeRaw(this.jsonPrefix); } - String jsonpFunction = - (object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null); - if (jsonpFunction != null) { - generator.writeRaw("/**/"); - generator.writeRaw(jsonpFunction + "("); - } - } - - @Override - protected void writeSuffix(JsonGenerator generator, Object object) throws IOException { - String jsonpFunction = - (object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null); - if (jsonpFunction != null) { - generator.writeRaw(");"); - } } } diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonValue.java b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonValue.java index 49baa93a40b..3af8f8f1e3d 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonValue.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJacksonValue.java @@ -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. @@ -45,9 +45,6 @@ public class MappingJacksonValue { @Nullable private FilterProvider filters; - @Nullable - private String jsonpFunction; - /** * Create a new instance wrapping the given POJO to be serialized. @@ -113,19 +110,4 @@ public class MappingJacksonValue { return this.filters; } - /** - * Set the name of the JSONP function name. - */ - public void setJsonpFunction(@Nullable String functionName) { - this.jsonpFunction = functionName; - } - - /** - * Return the configured JSONP function name. - */ - @Nullable - public String getJsonpFunction() { - return this.jsonpFunction; - } - } diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java index da292caadba..e4e0bf09d32 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java @@ -394,39 +394,6 @@ public class MappingJackson2HttpMessageConverterTests { assertThat(result, not(containsString("\"property2\":\"value\""))); } - @Test - public void jsonp() throws Exception { - MappingJacksonValue jacksonValue = new MappingJacksonValue("foo"); - jacksonValue.setSerializationView(MyJacksonView1.class); - jacksonValue.setJsonpFunction("callback"); - - MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); - this.converter.writeInternal(jacksonValue, null, outputMessage); - - assertEquals("/**/callback(\"foo\");", outputMessage.getBodyAsString(StandardCharsets.UTF_8)); - } - - @Test - public void jsonpAndJsonView() throws Exception { - MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); - JacksonViewBean bean = new JacksonViewBean(); - bean.setWithView1("with"); - bean.setWithView2("with"); - bean.setWithoutView("without"); - - MappingJacksonValue jacksonValue = new MappingJacksonValue(bean); - jacksonValue.setSerializationView(MyJacksonView1.class); - jacksonValue.setJsonpFunction("callback"); - this.converter.writeInternal(jacksonValue, null, outputMessage); - - String result = outputMessage.getBodyAsString(StandardCharsets.UTF_8); - assertThat(result, startsWith("/**/callback(")); - assertThat(result, endsWith(");")); - assertThat(result, containsString("\"withView1\":\"with\"")); - assertThat(result, not(containsString("\"withView2\":\"with\""))); - assertThat(result, not(containsString("\"withoutView\":\"without\""))); - } - @Test // SPR-13318 public void writeSubType() throws Exception { MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java deleted file mode 100644 index 0a383c6c57e..00000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractJsonpResponseBodyAdvice.java +++ /dev/null @@ -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. - * - *

Sub-classes must specify the query parameter name(s) to check for the name - * of the JSONP callback function. - * - *

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"); - } - -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java index daf207984c1..bb1f533613c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java @@ -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 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. - *

The parameter names configured by default are "jsonp" and "callback". - * @since 4.1 - * @see JSONP Wikipedia article - */ - public void setJsonpParameterNames(Set 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 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); - } } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java index 3a3b5e0182c..15976671195 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 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. @@ -255,25 +255,6 @@ public class RequestMappingHandlerAdapterTests { assertEquals("{\"status\":400,\"message\":\"body\"}", this.response.getContentAsString()); } - @Test - public void jsonpResponseBodyAdvice() throws Exception { - - List> converters = new ArrayList<>(); - converters.add(new MappingJackson2HttpMessageConverter()); - this.handlerAdapter.setMessageConverters(converters); - - this.webAppContext.registerSingleton("jsonpAdvice", JsonpAdvice.class); - this.webAppContext.refresh(); - - testJsonp("callback", true); - testJsonp("_callback", true); - testJsonp("_Call.bAcK", true); - testJsonp("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.", true); - - testJsonp("