From e98afc087f8da7349585c57ab66649689939375b Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Mon, 3 Jan 2011 14:38:28 +0000 Subject: [PATCH] SPR-7845 - FormHttpMessageConverter.read() always ignores post data when processing request (from Tomcat) --- .../http/server/ServletServerHttpRequest.java | 69 ++++++++++++++++--- .../http/server/ServletHttpRequestTests.java | 20 +++++- 2 files changed, 78 insertions(+), 11 deletions(-) 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 a3c67885940..0820abd82c9 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,11 +1,11 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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, @@ -16,11 +16,20 @@ package org.springframework.http.server; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.util.Arrays; import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpHeaders; @@ -35,13 +44,19 @@ import org.springframework.util.Assert; */ public class ServletServerHttpRequest implements ServerHttpRequest { + private static final String FORM_CONTENT_TYPE = "application/x-www-form-urlencoded"; + + private static final String POST_METHOD = "POST"; + + private static final String FORM_CHARSET = "UTF-8"; + private final HttpServletRequest servletRequest; private HttpHeaders headers; - /** * Construct a new instance of the ServletServerHttpRequest based on the given {@link HttpServletRequest} + * * @param servletRequest the HttpServletRequest */ public ServletServerHttpRequest(HttpServletRequest servletRequest) { @@ -49,7 +64,6 @@ public class ServletServerHttpRequest implements ServerHttpRequest { this.servletRequest = servletRequest; } - public HttpMethod getMethod() { return HttpMethod.valueOf(this.servletRequest.getMethod()); } @@ -57,8 +71,8 @@ public class ServletServerHttpRequest implements ServerHttpRequest { public URI getURI() { try { return new URI(servletRequest.getScheme(), null, servletRequest.getServerName(), - servletRequest.getServerPort(), servletRequest.getRequestURI(), - servletRequest.getQueryString(), null); + servletRequest.getServerPort(), servletRequest.getRequestURI(), servletRequest.getQueryString(), + null); } catch (URISyntaxException ex) { throw new IllegalStateException("Could not get HttpServletRequest URI: " + ex.getMessage(), ex); @@ -70,7 +84,8 @@ public class ServletServerHttpRequest implements ServerHttpRequest { this.headers = new HttpHeaders(); for (Enumeration headerNames = this.servletRequest.getHeaderNames(); headerNames.hasMoreElements();) { String headerName = (String) headerNames.nextElement(); - for (Enumeration headerValues = this.servletRequest.getHeaders(headerName); headerValues.hasMoreElements();) { + for (Enumeration headerValues = this.servletRequest.getHeaders(headerName); + headerValues.hasMoreElements();) { String headerValue = (String) headerValues.nextElement(); this.headers.add(headerName, headerValue); } @@ -80,7 +95,45 @@ public class ServletServerHttpRequest implements ServerHttpRequest { } public InputStream getBody() throws IOException { - return this.servletRequest.getInputStream(); + if (isFormSubmittal(this.servletRequest)) { + return getFormBody(this.servletRequest); + } + else { + return this.servletRequest.getInputStream(); + } + } + + private boolean isFormSubmittal(HttpServletRequest request) { + return FORM_CONTENT_TYPE.equals(request.getContentType()) && + POST_METHOD.equalsIgnoreCase(request.getMethod()); + } + + private InputStream getFormBody(HttpServletRequest request) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + Writer writer = new OutputStreamWriter(bos, FORM_CHARSET); + + Map form = request.getParameterMap(); + for (Iterator nameIterator = form.keySet().iterator(); nameIterator.hasNext();) { + String name = nameIterator.next(); + List values = Arrays.asList(form.get(name)); + for (Iterator valueIterator = values.iterator(); valueIterator.hasNext();) { + String value = valueIterator.next(); + writer.write(URLEncoder.encode(name, FORM_CHARSET)); + if (value != null) { + writer.write('='); + writer.write(URLEncoder.encode(value, FORM_CHARSET)); + if (valueIterator.hasNext()) { + writer.write('&'); + } + } + } + if (nameIterator.hasNext()) { + writer.append('&'); + } + } + writer.flush(); + + return new ByteArrayInputStream(bos.toByteArray()); } } diff --git a/org.springframework.web/src/test/java/org/springframework/http/server/ServletHttpRequestTests.java b/org.springframework.web/src/test/java/org/springframework/http/server/ServletHttpRequestTests.java index 1b43f80cbca..b3f6990995a 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/server/ServletHttpRequestTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/server/ServletHttpRequestTests.java @@ -1,11 +1,11 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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, @@ -19,7 +19,6 @@ package org.springframework.http.server; import java.net.URI; import java.util.List; -import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; @@ -28,6 +27,8 @@ import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.util.FileCopyUtils; +import static org.junit.Assert.*; + /** * @author Arjen Poutsma */ @@ -84,4 +85,17 @@ public class ServletHttpRequestTests { byte[] result = FileCopyUtils.copyToByteArray(request.getBody()); assertArrayEquals("Invalid content returned", content, result); } + + @Test + public void getFormBody() throws Exception { + mockRequest.setContentType("application/x-www-form-urlencoded"); + mockRequest.setMethod("POST"); + mockRequest.addParameter("name 1", "value 1"); + mockRequest.addParameter("name 2", new String[] {"value 2+1", "value 2+2"}); + mockRequest.addParameter("name 3", (String) null); + + byte[] result = FileCopyUtils.copyToByteArray(request.getBody()); + byte[] content = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3".getBytes("UTF-8"); + assertArrayEquals("Invalid content returned", content, result); + } } \ No newline at end of file