View Javadoc

1   package sparklr.common;
2   
3   import java.net.URI;
4   import java.util.Arrays;
5   import java.util.Collections;
6   import java.util.LinkedHashMap;
7   import java.util.Map;
8   
9   import org.junit.rules.MethodRule;
10  import org.junit.runners.model.FrameworkMethod;
11  import org.junit.runners.model.Statement;
12  import org.springframework.boot.test.TestRestTemplate;
13  import org.springframework.http.HttpEntity;
14  import org.springframework.http.HttpHeaders;
15  import org.springframework.http.HttpMethod;
16  import org.springframework.http.HttpStatus;
17  import org.springframework.http.MediaType;
18  import org.springframework.http.ResponseEntity;
19  import org.springframework.security.oauth2.client.test.RestTemplateHolder;
20  import org.springframework.util.MultiValueMap;
21  import org.springframework.util.StringUtils;
22  import org.springframework.web.client.RestOperations;
23  import org.springframework.web.client.RestTemplate;
24  import org.springframework.web.util.UriTemplate;
25  
26  /**
27   * <p>
28   * A rule that provides HTTP connectivity to test cases on the assumption that the server is available when test methods
29   * fire.
30   * </p>
31   * 
32   * @author Dave Syer
33   * 
34   */
35  public class HttpTestUtils implements MethodRule, RestTemplateHolder {
36  
37  	private static int DEFAULT_PORT = 8080;
38  
39  	private static String DEFAULT_HOST = "localhost";
40  
41  	private int port;
42  
43  	private String hostName = DEFAULT_HOST;
44  
45  	private RestOperations client;
46  
47  	private String prefix = "";
48  
49  	/**
50  	 * @return a new rule that sets up default host and port etc.
51  	 */
52  	public static HttpTestUtils standard() {
53  		return new HttpTestUtils();
54  	}
55  
56  	private HttpTestUtils() {
57  		setPort(DEFAULT_PORT);
58  	}
59  
60  	/**
61  	 * @param prefix
62  	 */
63  	public void setPrefix(String prefix) {
64  		if (!StringUtils.hasText(prefix)) {
65  			prefix = "";
66  		} else while (prefix.endsWith("/")) {
67  			prefix = prefix.substring(0, prefix.lastIndexOf("/"));
68  		}
69  		this.prefix = prefix;
70  	}
71  
72  	/**
73  	 * @param port the port to set
74  	 */
75  	public HttpTestUtils setPort(int port) {
76  		this.port = port;
77  		if (client == null) {
78  			client = createRestTemplate();
79  		}
80  		return this;
81  	}
82  
83  	/**
84  	 * @param hostName the hostName to set
85  	 */
86  	public HttpTestUtils setHostName(String hostName) {
87  		this.hostName = hostName;
88  		return this;
89  	}
90  
91  	public Statement apply(final Statement base, FrameworkMethod method, Object target) {
92  		
93  		return new Statement() {
94  			@Override
95  			public void evaluate() throws Throwable {
96  				base.evaluate();
97  			}
98  		};
99  
100 	}
101 
102 	public String getBaseUrl() {
103 		return "http://" + hostName + ":" + port + prefix;
104 	}
105 
106 	public String getUrl(String path) {
107 		if (path.startsWith("http")) {
108 			return path;
109 		}
110 		if (!path.startsWith("/")) {
111 			path = "/" + path;
112 		}
113 		return "http://" + hostName + ":" + port + prefix + path;
114 	}
115 
116 	public ResponseEntity<String> postForString(String path, MultiValueMap<String, String> formData) {
117 		HttpHeaders headers = new HttpHeaders();
118 		headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
119 		return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity<MultiValueMap<String, String>>(formData,
120 				headers), String.class);
121 	}
122 
123 	public ResponseEntity<String> postForString(String path, HttpHeaders headers, MultiValueMap<String, String> formData) {
124 		HttpHeaders actualHeaders = new HttpHeaders();
125 		actualHeaders.putAll(headers);
126 		headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
127 		return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity<MultiValueMap<String, String>>(formData,
128 				actualHeaders), String.class);
129 	}
130 
131 	@SuppressWarnings("rawtypes")
132 	public ResponseEntity<Map> postForMap(String path, MultiValueMap<String, String> formData) {
133 		return postForMap(path, new HttpHeaders(), formData);
134 	}
135 
136 	@SuppressWarnings("rawtypes")
137 	public ResponseEntity<Map> postForMap(String path, HttpHeaders headers, MultiValueMap<String, String> formData) {
138 		if (headers.getContentType() == null) {
139 			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
140 		}
141 		return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity<MultiValueMap<String, String>>(formData,
142 				headers), Map.class);
143 	}
144 
145 	public ResponseEntity<Void> postForStatus(String path, MultiValueMap<String, String> formData) {
146 		return postForStatus(this.client, path, formData);
147 	}
148 
149 	public ResponseEntity<Void> postForStatus(String path, HttpHeaders headers, MultiValueMap<String, String> formData) {
150 		return postForStatus(this.client, path, headers, formData);
151 	}
152 
153 	private ResponseEntity<Void> postForStatus(RestOperations client, String path,
154 			MultiValueMap<String, String> formData) {
155 		return postForStatus(client, path, new HttpHeaders(), formData);
156 	}
157 
158 	private ResponseEntity<Void> postForStatus(RestOperations client, String path, HttpHeaders headers,
159 			MultiValueMap<String, String> formData) {
160 		HttpHeaders actualHeaders = new HttpHeaders();
161 		actualHeaders.putAll(headers);
162 		actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
163 		return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity<MultiValueMap<String, String>>(formData,
164 				actualHeaders), (Class<Void>) null);
165 	}
166 
167 	public ResponseEntity<Void> postForRedirect(String path, HttpHeaders headers, MultiValueMap<String, String> params) {
168 		ResponseEntity<Void> exchange = postForStatus(path, headers, params);
169 
170 		if (exchange.getStatusCode() != HttpStatus.FOUND) {
171 			throw new IllegalStateException("Expected 302 but server returned status code " + exchange.getStatusCode());
172 		}
173 
174 		if (exchange.getHeaders().containsKey("Set-Cookie")) {
175 			String cookie = exchange.getHeaders().getFirst("Set-Cookie");
176 			headers.set("Cookie", cookie);
177 		}
178 
179 		String location = exchange.getHeaders().getLocation().toString();
180 
181 		return client.exchange(location, HttpMethod.GET, new HttpEntity<Void>(null, headers), (Class<Void>) null);
182 	}
183 
184 	public ResponseEntity<String> getForString(String path) {
185 		return getForString(path, new HttpHeaders());
186 	}
187 
188 	public ResponseEntity<String> getForString(String path, final HttpHeaders headers) {
189 		return client.exchange(getUrl(path), HttpMethod.GET, new HttpEntity<Void>((Void) null, headers), String.class);
190 	}
191 
192 	public ResponseEntity<String> getForString(String path, final HttpHeaders headers, Map<String, String> uriVariables) {
193 		return client.exchange(getUrl(path), HttpMethod.GET, new HttpEntity<Void>((Void) null, headers), String.class,
194 				uriVariables);
195 	}
196 
197 	public ResponseEntity<Void> getForResponse(String path, final HttpHeaders headers, Map<String, String> uriVariables) {
198 		HttpEntity<Void> request = new HttpEntity<Void>(null, headers);
199 		return client.exchange(getUrl(path), HttpMethod.GET, request, (Class<Void>) null, uriVariables);
200 	}
201 
202 	public ResponseEntity<Void> getForResponse(String path, HttpHeaders headers) {
203 		return getForResponse(path, headers, Collections.<String, String> emptyMap());
204 	}
205 
206 	public HttpStatus getStatusCode(String path, final HttpHeaders headers) {
207 		ResponseEntity<Void> response = getForResponse(path, headers);
208 		return response.getStatusCode();
209 	}
210 
211 	public HttpStatus getStatusCode(String path) {
212 		return getStatusCode(getUrl(path), null);
213 	}
214 
215 	public void setRestTemplate(RestOperations restTemplate) {
216 		client = restTemplate;
217 	}
218 
219 	public RestOperations getRestTemplate() {
220 		return client;
221 	}
222 
223 	public RestOperations createRestTemplate() {
224 		RestTemplate client = new TestRestTemplate();
225 		return client;
226 	}
227 
228 	public UriBuilder buildUri(String url) {
229 		return UriBuilder.fromUri(url.startsWith("http:") ? url : getUrl(url));
230 	}
231 
232 	public static class UriBuilder {
233 
234 		private final String url;
235 
236 		private Map<String, String> params = new LinkedHashMap<String, String>();
237 
238 		public UriBuilder(String url) {
239 			this.url = url;
240 		}
241 
242 		public static UriBuilder fromUri(String url) {
243 			return new UriBuilder(url);
244 		}
245 
246 		public UriBuilder queryParam(String key, String value) {
247 			params.put(key, value);
248 			return this;
249 		}
250 
251 		public String pattern() {
252 			StringBuilder builder = new StringBuilder();
253 			// try {
254 			builder.append(url.replace(" ", "+"));
255 			if (!params.isEmpty()) {
256 				builder.append("?");
257 				boolean first = true;
258 				for (String key : params.keySet()) {
259 					if (!first) {
260 						builder.append("&");
261 					}
262 					else {
263 						first = false;
264 					}
265 					String value = params.get(key);
266 					if (value.contains("=")) {
267 						value = value.replace("=", "%3D");
268 					}
269 					builder.append(key + "={" + key + "}");
270 				}
271 			}
272 			return builder.toString();
273 
274 		}
275 
276 		public Map<String, String> params() {
277 			return params;
278 		}
279 
280 		public URI build() {
281 			return new UriTemplate(pattern()).expand(params);
282 		}
283 	}
284 
285 }