SPR-6969 - Introduce HttpEntity

This commit is contained in:
Arjen Poutsma
2010-03-11 16:42:25 +00:00
parent fc0a6ce40c
commit 63076d0865
9 changed files with 670 additions and 59 deletions

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2002-2010 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.http;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* @author Arjen Poutsma
*/
public class HttpEntityTests {
@Test
public void noHeaders() {
String body = "foo";
HttpEntity<String> entity = new HttpEntity<String>(body);
assertSame(body, entity.getBody());
assertTrue(entity.getHeaders().isEmpty());
}
@Test
public void contentType() {
MediaType contentType = MediaType.TEXT_PLAIN;
HttpEntity<String> entity = new HttpEntity<String>("foo", contentType);
assertEquals(contentType, entity.getHeaders().getContentType());
assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type"));
}
@Test
public void multiValueMap() {
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.set("Content-Type", "text/plain");
HttpEntity<String> entity = new HttpEntity<String>("foo", map);
assertEquals(MediaType.TEXT_PLAIN, entity.getHeaders().getContentType());
assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type"));
}
@Test
public void map() {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("Content-Type", "text/plain");
HttpEntity<String> entity = new HttpEntity<String>("foo", map);
assertEquals(MediaType.TEXT_PLAIN, entity.getHeaders().getContentType());
assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type"));
}
}

View File

@@ -36,6 +36,7 @@ import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.MediaType;
import org.springframework.http.MockHttpInputMessage;
import org.springframework.http.MockHttpOutputMessage;
@@ -108,7 +109,8 @@ public class FormHttpMessageConverterTests {
Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
parts.add("logo", logo);
Source xml = new StreamSource(new StringReader("<root><child/></root>"));
parts.add("xml", xml);
HttpEntity<Source> entity = new HttpEntity<Source>(xml, MediaType.TEXT_XML);
parts.add("xml", entity);
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
converter.write(parts, MediaType.MULTIPART_FORM_DATA, outputMessage);
@@ -145,7 +147,7 @@ public class FormHttpMessageConverterTests {
item = (FileItem) items.get(4);
assertEquals("xml", item.getFieldName());
assertEquals("application/xml", item.getContentType());
assertEquals("text/xml", item.getContentType());
}
private static class MockHttpOutputMessageRequestContext implements RequestContext {

View File

@@ -20,6 +20,8 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
@@ -47,7 +49,9 @@ import org.mortbay.jetty.servlet.ServletHolder;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.CommonsClientHttpRequestFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -64,12 +68,14 @@ public class RestTemplateIntegrationTests {
private static final String URI = "http://localhost:8889";
private static MediaType contentType;
@BeforeClass
public static void startJettyServer() throws Exception {
jettyServer = new Server(8889);
Context jettyContext = new Context(jettyServer, "/");
byte[] bytes = helloWorld.getBytes("UTF-8");
String contentType = "text/plain;charset=utf-8";
contentType = new MediaType("text", "plain", Collections.singletonMap("charset", "utf-8"));
jettyContext.addServlet(new ServletHolder(new GetServlet(bytes, contentType)), "/get");
jettyContext.addServlet(new ServletHolder(new GetServlet(new byte[0], contentType)), "/get/nothing");
jettyContext.addServlet(
@@ -100,6 +106,14 @@ public class RestTemplateIntegrationTests {
assertEquals("Invalid content", helloWorld, s);
}
@Test
public void getEntity() {
HttpEntity<String> entity = template.getForEntity(URI + "/{method}", String.class, "get");
assertEquals("Invalid content", helloWorld, entity.getBody());
assertFalse("No headers", entity.getHeaders().isEmpty());
assertEquals("Invalid content-type", contentType, entity.getHeaders().getContentType());
}
@Test
public void getNoResponse() {
String s = template.getForObject(URI + "/get/nothing", String.class);
@@ -112,6 +126,13 @@ public class RestTemplateIntegrationTests {
assertEquals("Invalid location", new URI(URI + "/post/1"), location);
}
@Test
public void postForLocationEntity() throws URISyntaxException {
HttpEntity<String> entity = new HttpEntity<String>(helloWorld, new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
URI location = template.postForLocation(URI + "/{method}", entity, "post");
assertEquals("Invalid location", new URI(URI + "/post/1"), location);
}
@Test
public void postForObject() throws URISyntaxException {
String s = template.postForObject(URI + "/{method}", helloWorld, String.class, "post");
@@ -156,6 +177,7 @@ public class RestTemplateIntegrationTests {
template.postForLocation(URI + "/multipart", parts);
}
/** Servlet that returns and error message for a given status code. */
private static class ErrorServlet extends GenericServlet {
@@ -175,9 +197,9 @@ public class RestTemplateIntegrationTests {
private final byte[] buf;
private final String contentType;
private final MediaType contentType;
private GetServlet(byte[] buf, String contentType) {
private GetServlet(byte[] buf, MediaType contentType) {
this.buf = buf;
this.contentType = contentType;
}
@@ -185,7 +207,7 @@ public class RestTemplateIntegrationTests {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(contentType);
response.setContentType(contentType.toString());
response.setContentLength(buf.length);
FileCopyUtils.copy(buf, response.getOutputStream());
}
@@ -199,9 +221,9 @@ public class RestTemplateIntegrationTests {
private final byte[] buf;
private final String contentType;
private final MediaType contentType;
private PostServlet(String s, String location, byte[] buf, String contentType) {
private PostServlet(String s, String location, byte[] buf, MediaType contentType) {
this.s = s;
this.location = location;
this.buf = buf;
@@ -218,7 +240,7 @@ public class RestTemplateIntegrationTests {
response.setStatus(HttpServletResponse.SC_CREATED);
response.setHeader("Location", location);
response.setContentLength(buf.length);
response.setContentType(contentType);
response.setContentType(contentType.toString());
FileCopyUtils.copy(buf, response.getOutputStream());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -28,6 +28,7 @@ import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
@@ -176,6 +177,36 @@ public class RestTemplateTests {
verifyMocks();
}
@Test
public void getForEntity() throws Exception {
expect(converter.canRead(String.class, null)).andReturn(true);
MediaType textPlain = new MediaType("text", "plain");
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(textPlain));
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.GET)).andReturn(request);
HttpHeaders requestHeaders = new HttpHeaders();
expect(request.getHeaders()).andReturn(requestHeaders);
expect(request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(textPlain);
expect(response.getHeaders()).andReturn(responseHeaders).times(2);
expect(converter.canRead(String.class, textPlain)).andReturn(true);
String expected = "Hello World";
expect(converter.read(String.class, response)).andReturn(expected);
response.close();
replayMocks();
HttpEntity<String> result = template.getForEntity("http://example.com", String.class);
assertEquals("Invalid GET result", expected, result.getBody());
assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept"));
assertEquals("Invalid Content-Type header", textPlain, result.getHeaders().getContentType());
verifyMocks();
}
@Test
public void headForHeaders() throws Exception {
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.HEAD)).andReturn(request);
@@ -215,6 +246,60 @@ public class RestTemplateTests {
verifyMocks();
}
@Test
public void postForLocationEntityContentType() throws Exception {
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request);
String helloWorld = "Hello World";
MediaType contentType = MediaType.TEXT_PLAIN;
expect(converter.canWrite(String.class, contentType)).andReturn(true);
HttpHeaders requestHeaders = new HttpHeaders();
expect(request.getHeaders()).andReturn(requestHeaders);
converter.write(helloWorld, contentType, request);
expect(request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
URI expected = new URI("http://example.com/hotels");
responseHeaders.setLocation(expected);
expect(response.getHeaders()).andReturn(responseHeaders);
response.close();
replayMocks();
HttpEntity<String> entity = new HttpEntity<String>(helloWorld, contentType);
URI result = template.postForLocation("http://example.com", entity);
assertEquals("Invalid POST result", expected, result);
verifyMocks();
}
@Test
public void postForLocationEntityCustomHeader() throws Exception {
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request);
String helloWorld = "Hello World";
expect(converter.canWrite(String.class, null)).andReturn(true);
HttpHeaders requestHeaders = new HttpHeaders();
expect(request.getHeaders()).andReturn(requestHeaders);
converter.write(helloWorld, null, request);
expect(request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
URI expected = new URI("http://example.com/hotels");
responseHeaders.setLocation(expected);
expect(response.getHeaders()).andReturn(responseHeaders);
response.close();
replayMocks();
HttpEntity<String> entity = new HttpEntity<String>(helloWorld, Collections.singletonMap("MyHeader", "MyValue"));
URI result = template.postForLocation("http://example.com", entity);
assertEquals("Invalid POST result", expected, result);
assertEquals("No custom header set", "MyValue", requestHeaders.getFirst("MyHeader"));
verifyMocks();
}
@Test
public void postForLocationNoLocation() throws Exception {
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request);
@@ -283,6 +368,37 @@ public class RestTemplateTests {
verifyMocks();
}
@Test
public void postForEntity() throws Exception {
MediaType textPlain = new MediaType("text", "plain");
expect(converter.canRead(Integer.class, null)).andReturn(true);
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(textPlain));
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(this.request);
HttpHeaders requestHeaders = new HttpHeaders();
expect(this.request.getHeaders()).andReturn(requestHeaders);
String request = "Hello World";
expect(converter.canWrite(String.class, null)).andReturn(true);
converter.write(request, null, this.request);
expect(this.request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(textPlain);
expect(response.getHeaders()).andReturn(responseHeaders).times(2);
Integer expected = 42;
expect(converter.canRead(Integer.class, textPlain)).andReturn(true);
expect(converter.read(Integer.class, response)).andReturn(expected);
response.close();
replayMocks();
HttpEntity<Integer> result = template.postForEntity("http://example.com", request, Integer.class);
assertEquals("Invalid POST result", expected, result.getBody());
assertEquals("Invalid Content-Type", textPlain, result.getHeaders().getContentType());
assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept"));
verifyMocks();
}
@Test
public void postForObjectNull() throws Exception {
MediaType textPlain = new MediaType("text", "plain");
@@ -301,7 +417,34 @@ public class RestTemplateTests {
response.close();
replayMocks();
template.postForObject("http://example.com", null, Integer.class);
Integer result = template.postForObject("http://example.com", null, Integer.class);
assertNull("Invalid POST result", result);
assertEquals("Invalid content length", 0, requestHeaders.getContentLength());
verifyMocks();
}
@Test
public void postForEntityNull() throws Exception {
MediaType textPlain = new MediaType("text", "plain");
expect(converter.canRead(Integer.class, null)).andReturn(true);
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(textPlain));
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request);
HttpHeaders requestHeaders = new HttpHeaders();
expect(request.getHeaders()).andReturn(requestHeaders).times(2);
expect(request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(textPlain);
expect(response.getHeaders()).andReturn(responseHeaders).times(2);
expect(converter.canRead(Integer.class, textPlain)).andReturn(true);
expect(converter.read(Integer.class, response)).andReturn(null);
response.close();
replayMocks();
HttpEntity<Integer> result = template.postForEntity("http://example.com", null, Integer.class);
assertFalse("Invalid POST result", result.hasBody());
assertEquals("Invalid Content-Type", textPlain, result.getHeaders().getContentType());
assertEquals("Invalid content length", 0, requestHeaders.getContentLength());
verifyMocks();