/*
2. * Copyright 2002-2010 the original author or authors.
3. *
4. * Licensed under the Apache License, Version 2.0 (the "License");
5. * you may not use this file except in compliance with the License.
6. * You may obtain a copy of the License at
7. *
8. * http://www.apache.org/licenses/LICENSE-2.0
9. *
10. * Unless required by applicable law or agreed to in writing, software
11. * distributed under the License is distributed on an "AS IS" BASIS,
12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13. * See the License for the specific language governing permissions and
14. * limitations under the License.
15. */
16.
17. package org.springframework.web.client;
18.
19. import java.io.IOException;
20. import java.io.UnsupportedEncodingException;
21. import java.net.URI;
22. import java.net.URISyntaxException;
23. import java.nio.charset.Charset;
24. import java.util.Collections;
25. import java.util.EnumSet;
26. import java.util.List;
27. import java.util.Set;
28. import javax.servlet.GenericServlet;
29. import javax.servlet.ServletException;
30. import javax.servlet.ServletRequest;
31. import javax.servlet.ServletResponse;
32. import javax.servlet.http.HttpServlet;
33. import javax.servlet.http.HttpServletRequest;
34. import javax.servlet.http.HttpServletResponse;
35.
36. import org.apache.commons.fileupload.FileItem;
37. import org.apache.commons.fileupload.FileItemFactory;
38. import org.apache.commons.fileupload.FileUploadException;
39. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
40. import org.apache.commons.fileupload.servlet.ServletFileUpload;
41. import org.junit.AfterClass;
42. import org.junit.Before;
43. import org.junit.BeforeClass;
44. import org.junit.Test;
45. import org.mortbay.jetty.Server;
46. import org.mortbay.jetty.servlet.Context;
47. import org.mortbay.jetty.servlet.ServletHolder;
48.
49. import org.springframework.core.io.ClassPathResource;
50. import org.springframework.core.io.Resource;
51. import org.springframework.http.HttpEntity;
52. import org.springframework.http.HttpHeaders;
53. import org.springframework.http.HttpMethod;
54. import org.springframework.http.HttpStatus;
55. import org.springframework.http.MediaType;
56. import org.springframework.http.ResponseEntity;
57. import org.springframework.http.client.CommonsClientHttpRequestFactory;
58. import org.springframework.http.client.FreePortScanner;
59. import org.springframework.util.FileCopyUtils;
60. import org.springframework.util.LinkedMultiValueMap;
61. import org.springframework.util.MultiValueMap;
62.
63. import static org.junit.Assert.*;
64.
65. /** @author Arjen Poutsma */
66. public class RestTemplateIntegrationTests {
67.
68. private RestTemplate template;
69.
70. private static Server jettyServer;
71.
72. private static String helloWorld = "H\u00e9llo W\u00f6rld";
73.
74. private static String baseUrl;
75.
76. private static MediaType contentType;
77.
78. @BeforeClass
79. public static void startJettyServer() throws Exception {
80. int port = FreePortScanner.getFreePort();
81. jettyServer = new Server(port);
82. baseUrl = "http://localhost:" + port;
83. Context jettyContext = new Context(jettyServer, "/");
84. byte[] bytes = helloWorld.getBytes("UTF-8");
85. contentType = new MediaType("text", "plain", Collections.singletonMap("charset", "utf-8"));
86. jettyContext.addServlet(new ServletHolder(new GetServlet(bytes, contentType)), "/get");
87. jettyContext.addServlet(new ServletHolder(new GetServlet(new byte[0], contentType)), "/get/nothing");
88. jettyContext.addServlet(
89. new ServletHolder(new PostServlet(helloWorld, baseUrl + "/post/1", bytes, contentType)),
90. "/post");
91. jettyContext.addServlet(new ServletHolder(new ErrorServlet(404)), "/errors/notfound");
92. jettyContext.addServlet(new ServletHolder(new ErrorServlet(500)), "/errors/server");
93. jettyContext.addServlet(new ServletHolder(new UriServlet()), "/uri/*");
94. jettyContext.addServlet(new ServletHolder(new MultipartServlet()), "/multipart");
95. jettyServer.start();
96. }
97.
98. @Before
99. public void createTemplate() {
100. template = new RestTemplate(new CommonsClientHttpRequestFactory());
101. }
102.
103. @AfterClass
104. public static void stopJettyServer() throws Exception {
105. if (jettyServer != null) {
106. jettyServer.stop();
107. }
108. }
109.
110. @Test
111. public void getString() {
112. String s = template.getForObject(baseUrl + "/{method}", String.class, "get");
113. assertEquals("Invalid content", helloWorld, s);
114. }
115.
116. @Test
117. public void getEntity() {
118. ResponseEntity<String> entity = template.getForEntity(baseUrl + "/{method}", String.class, "get");
119. assertEquals("Invalid content", helloWorld, entity.getBody());
120. assertFalse("No headers", entity.getHeaders().isEmpty());
121. assertEquals("Invalid content-type", contentType, entity.getHeaders().getContentType());
122. assertEquals("Invalid status code", HttpStatus.OK, entity.getStatusCode());
123. }
124.
125. @Test
126. public void getNoResponse() {
127. String s = template.getForObject(baseUrl + "/get/nothing", String.class);
128. assertEquals("Invalid content", "", s);
129. }
130.
131. @Test
132. public void postForLocation() throws URISyntaxException {
133. URI location = template.postForLocation(baseUrl + "/{method}", helloWorld, "post");
134. assertEquals("Invalid location", new URI(baseUrl + "/post/1"), location);
135. }
136.
137. @Test
138. public void postForLocationEntity() throws URISyntaxException {
139. HttpHeaders entityHeaders = new HttpHeaders();
140. entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
141. HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
142. URI location = template.postForLocation(baseUrl + "/{method}", entity, "post");
143. assertEquals("Invalid location", new URI(baseUrl + "/post/1"), location);
144. }
145.
146. @Test
147. public void postForObject() throws URISyntaxException {
148. String s = template.postForObject(baseUrl + "/{method}", helloWorld, String.class, "post");
149. assertEquals("Invalid content", helloWorld, s);
150. }
151.
152. @Test
153. public void notFound() {
154. try {
155. template.execute(baseUrl + "/errors/notfound", HttpMethod.GET, null, null);
156. fail("HttpClientErrorException expected");
157. }
158. catch (HttpClientErrorException ex) {
159. assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode());
160. assertNotNull(ex.getStatusText());
161. assertNotNull(ex.getResponseBodyAsString());
162. }
163. }
164.
165. @Test
166. public void serverError() {
167. try {
168. template.execute(baseUrl + "/errors/server", HttpMethod.GET, null, null);
169. fail("HttpServerErrorException expected");
170. }
171. catch (HttpServerErrorException ex) {
172. assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, ex.getStatusCode());
173. assertNotNull(ex.getStatusText());
174. assertNotNull(ex.getResponseBodyAsString());
175. }
176. }
177.
178. @Test
179. public void optionsForAllow() throws URISyntaxException {
180. Set<HttpMethod> allowed = template.optionsForAllow(new URI(baseUrl + "/get"));
181. assertEquals("Invalid response",
182. EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.TRACE), allowed);
183. }
184.
185. @Test
186. public void uri() throws InterruptedException, URISyntaxException {
187. String result = template.getForObject(baseUrl + "/uri/{query}", String.class, "Z\u00fcrich");
188. assertEquals("Invalid request URI", "/uri/Z%C3%BCrich", result);
189.
190. result = template.getForObject(baseUrl + "/uri/query={query}", String.class, "foo@bar");
191. assertEquals("Invalid request URI", "/uri/query=foo@bar", result);
192.
193. result = template.getForObject(baseUrl + "/uri/query={query}", String.class, "T\u014dky\u014d");
194. assertEquals("Invalid request URI", "/uri/query=T%C5%8Dky%C5%8D", result);
195. }
196.
197. @Test
198. public void multipart() throws UnsupportedEncodingException {
199. MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
200. parts.add("name 1", "value 1");
201. parts.add("name 2", "value 2+1");
202. parts.add("name 2", "value 2+2");
203. Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
204. parts.add("logo", logo);
205.
206. template.postForLocation(baseUrl + "/multipart", parts);
207. }
208.
209. @Test
210. public void exchangeGet() throws Exception {
211. HttpHeaders requestHeaders = new HttpHeaders();
212. requestHeaders.set("MyHeader", "MyValue");
213. HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
214. ResponseEntity<String> response =
215. template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get");
216. assertEquals("Invalid content", helloWorld, response.getBody());
217. }
218.
219. @Test
220. public void exchangePost() throws Exception {
221. HttpHeaders requestHeaders = new HttpHeaders();
222. requestHeaders.set("MyHeader", "MyValue");
223. requestHeaders.setContentType(MediaType.TEXT_PLAIN);
224. HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
225. HttpEntity<?> result = template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, null, "post");
226. assertEquals("Invalid location", new URI(baseUrl + "/post/1"), result.getHeaders().getLocation());
227. assertFalse(result.hasBody());
228. }
229.
230. /** Servlet that returns and error message for a given status code. */
231. private static class ErrorServlet extends GenericServlet {
232.
233. private final int sc;
234.
235. private ErrorServlet(int sc) {
236. this.sc = sc;
237. }
238.
239. @Override
240. public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
241. ((HttpServletResponse) response).sendError(sc);
242. }
243. }
244.
245. private static class GetServlet extends HttpServlet {
246.
247. private final byte[] buf;
248.
249. private final MediaType contentType;
250.
251. private GetServlet(byte[] buf, MediaType contentType) {
252. this.buf = buf;
253. this.contentType = contentType;
254. }
255.
256. @Override
257. protected void doGet(HttpServletRequest request, HttpServletResponse response)
258. throws ServletException, IOException {
259. response.setContentType(contentType.toString());
260. response.setContentLength(buf.length);
261. FileCopyUtils.copy(buf, response.getOutputStream());
262. }
263. }
264.
265. private static class PostServlet extends HttpServlet {
266.
267. private final String s;
268.
269. private final String location;
270.
271. private final byte[] buf;
272.
273. private final MediaType contentType;
274.
275. private PostServlet(String s, String location, byte[] buf, MediaType contentType) {
276. this.s = s;
277. this.location = location;
278. this.buf = buf;
279. this.contentType = contentType;
280. }
281.
282. @Override
283. protected void doPost(HttpServletRequest request, HttpServletResponse response)
284. throws ServletException, IOException {
285. assertTrue("Invalid request content-length", request.getContentLength() > 0);
286. assertNotNull("No content-type", request.getContentType());
287. String body = FileCopyUtils.copyToString(request.getReader());
288. assertEquals("Invalid request body", s, body);
289. response.setStatus(HttpServletResponse.SC_CREATED);
290. response.setHeader("Location", location);
291. response.setContentLength(buf.length);
292. response.setContentType(contentType.toString());
293. FileCopyUtils.copy(buf, response.getOutputStream());
294. }
295. }
296.
297. private static class UriServlet extends HttpServlet {
298.
299. @Override
300. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
301. resp.setContentType("text/plain");
302. resp.setCharacterEncoding("UTF-8");
303. resp.getWriter().write(req.getRequestURI());
304. }
305. }
306.
307. private static class MultipartServlet extends HttpServlet {
308.
309. @Override
310. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
311. assertTrue(ServletFileUpload.isMultipartContent(req));
312. FileItemFactory factory = new DiskFileItemFactory();
313. ServletFileUpload upload = new ServletFileUpload(factory);
314. try {
315. List items = upload.parseRequest(req);
316. assertEquals(4, items.size());
317. FileItem item = (FileItem) items.get(0);
318. assertTrue(item.isFormField());
319. assertEquals("name 1", item.getFieldName());
320. assertEquals("value 1", item.getString());
321.
322. item = (FileItem) items.get(1);
323. assertTrue(item.isFormField());
324. assertEquals("name 2", item.getFieldName());
325. assertEquals("value 2+1", item.getString());
326.
327. item = (FileItem) items.get(2);
328. assertTrue(item.isFormField());
329. assertEquals("name 2", item.getFieldName());
330. assertEquals("value 2+2", item.getString());
331.
332. item = (FileItem) items.get(3);
333. assertFalse(item.isFormField());
334. assertEquals("logo", item.getFieldName());
335. assertEquals("logo.jpg", item.getName());
336. assertEquals("image/jpeg", item.getContentType());
337. }
338. catch (FileUploadException ex) {
339. throw new ServletException(ex);
340. }
341.
342. }
343. }
344.
345. } [color=darkred][/color]