diff --git a/build-spring-framework/resources/changelog.txt b/build-spring-framework/resources/changelog.txt index 6314a068d09..5e6ef950c63 100644 --- a/build-spring-framework/resources/changelog.txt +++ b/build-spring-framework/resources/changelog.txt @@ -42,6 +42,7 @@ Changes in version 3.1.1 (2012-02-13) * fixed request mapping bug involving direct vs pattern path matches with HTTP methods * removed check for HTTP "POST" when resolving multipart request controller method arguments * updated @RequestMapping and reference docs wrt differences between @MVC 3.1 and @MVC 2.5-3.0 +* ServletServerHttpRequest/Response fall back on the Content-Type and encoding of the request Changes in version 3.1 GA (2011-12-12) diff --git a/org.springframework.web/src/main/java/org/springframework/http/MediaType.java b/org.springframework.web/src/main/java/org/springframework/http/MediaType.java index d467e1feaeb..6d0f75fe4f5 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/MediaType.java +++ b/org.springframework.web/src/main/java/org/springframework/http/MediaType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -450,6 +450,14 @@ public class MediaType implements Comparable { return this.parameters.get(name); } + /** + * Return all generic parameter values. + * @return a read-only map, possibly empty, never null + */ + public Map getParameters() { + return parameters; + } + /** * Indicate whether this {@code MediaType} includes the given media type. *

For instance, {@code text/*} includes {@code text/plain} and {@code text/html}, and {@code application/*+xml} diff --git a/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpRequest.java b/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpRequest.java index e93367b6515..3c5459e615b 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpRequest.java +++ b/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -25,15 +25,19 @@ import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Enumeration; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; + import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.util.Assert; /** @@ -90,14 +94,31 @@ public class ServletServerHttpRequest implements ServerHttpRequest { public HttpHeaders getHeaders() { if (this.headers == null) { this.headers = new HttpHeaders(); - for (Enumeration headerNames = this.servletRequest.getHeaderNames(); headerNames.hasMoreElements();) { + for (Enumeration headerNames = this.servletRequest.getHeaderNames(); headerNames.hasMoreElements();) { String headerName = (String) headerNames.nextElement(); - for (Enumeration headerValues = this.servletRequest.getHeaders(headerName); + for (Enumeration headerValues = this.servletRequest.getHeaders(headerName); headerValues.hasMoreElements();) { String headerValue = (String) headerValues.nextElement(); this.headers.add(headerName, headerValue); } } + // HttpServletRequest exposes some headers as properties: we should include those if not already present + if (this.headers.getContentType() == null && this.servletRequest.getContentType() != null) { + MediaType contentType = MediaType.parseMediaType(this.servletRequest.getContentType()); + this.headers.setContentType(contentType); + } + if (this.headers.getContentType() != null && this.headers.getContentType().getCharSet() == null && + this.servletRequest.getCharacterEncoding() != null) { + MediaType oldContentType = this.headers.getContentType(); + Charset charSet = Charset.forName(this.servletRequest.getCharacterEncoding()); + Map params = new HashMap(oldContentType.getParameters()); + params.put("charset", charSet.toString()); + MediaType newContentType = new MediaType(oldContentType.getType(), oldContentType.getSubtype(), params); + this.headers.setContentType(newContentType); + } + if (this.headers.getContentLength() == -1 && this.servletRequest.getContentLength() != -1) { + this.headers.setContentLength(this.servletRequest.getContentLength()); + } } return this.headers; } diff --git a/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java b/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java index 9752c4259d8..985085e51e9 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java +++ b/org.springframework.web/src/main/java/org/springframework/http/server/ServletServerHttpResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -83,6 +83,14 @@ public class ServletServerHttpResponse implements ServerHttpResponse { this.servletResponse.addHeader(headerName, headerValue); } } + // HttpServletResponse exposes some headers as properties: we should include those if not already present + if (this.servletResponse.getContentType() == null && this.headers.getContentType() != null) { + this.servletResponse.setContentType(this.headers.getContentType().toString()); + } + if (this.servletResponse.getCharacterEncoding() == null && this.headers.getContentType() != null && + this.headers.getContentType().getCharSet() != null) { + this.servletResponse.setCharacterEncoding(this.headers.getContentType().getCharSet().name()); + } this.headersWritten = true; } } diff --git a/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpRequestTests.java b/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpRequestTests.java index 30fd57b6b79..1a2ec75e574 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpRequestTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpRequestTests.java @@ -1,11 +1,11 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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 + * 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, @@ -17,6 +17,7 @@ package org.springframework.http.server; import java.net.URI; +import java.nio.charset.Charset; import java.util.List; import org.junit.Before; @@ -24,6 +25,7 @@ import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.util.FileCopyUtils; @@ -67,6 +69,8 @@ public class ServletServerHttpRequestTests { mockRequest.addHeader(headerName, headerValue1); String headerValue2 = "value2"; mockRequest.addHeader(headerName, headerValue2); + mockRequest.setContentType("text/plain"); + mockRequest.setCharacterEncoding("UTF-8"); HttpHeaders headers = request.getHeaders(); assertNotNull("No HttpHeaders returned", headers); @@ -75,6 +79,8 @@ public class ServletServerHttpRequestTests { assertEquals("Invalid header values returned", 2, headerValues.size()); assertTrue("Invalid header values returned", headerValues.contains(headerValue1)); assertTrue("Invalid header values returned", headerValues.contains(headerValue2)); + assertEquals("Invalid Content-Type", new MediaType("text", "plain", Charset.forName("UTF-8")), + headers.getContentType()); } @Test diff --git a/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpResponseTests.java b/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpResponseTests.java index bad9ccdb840..fd9392f108d 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpResponseTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/server/ServletServerHttpResponseTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 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. @@ -16,16 +16,19 @@ package org.springframework.http.server; +import java.nio.charset.Charset; import java.util.List; -import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.util.FileCopyUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.util.FileCopyUtils; + +import static org.junit.Assert.*; /** * @author Arjen Poutsma @@ -56,12 +59,16 @@ public class ServletServerHttpResponseTests { headers.add(headerName, headerValue1); String headerValue2 = "value2"; headers.add(headerName, headerValue2); + headers.setContentType(new MediaType("text", "plain", Charset.forName("UTF-8"))); response.close(); assertTrue("Header not set", mockResponse.getHeaderNames().contains(headerName)); List headerValues = mockResponse.getHeaders(headerName); assertTrue("Header not set", headerValues.contains(headerValue1)); assertTrue("Header not set", headerValues.contains(headerValue2)); + assertEquals("Invalid Content-Type", "text/plain;charset=UTF-8", mockResponse.getHeader("Content-Type")); + assertEquals("Invalid Content-Type", "text/plain;charset=UTF-8", mockResponse.getContentType()); + assertEquals("Invalid Content-Type", "UTF-8", mockResponse.getCharacterEncoding()); } @Test