This implementation creates an HttpMethod with the request's target + * URL as well as the "Accept-Language" and "Accept-Encoding" headers. If + * the method is "POST" or "PUT", the "Content-Type" header will also be + * set as specified in the given request. + * @param request the HTTP request to create a method for + * @return the HttpMethod instance + */ + private HttpMethod createHttpMethod(HttpRequest request) { + String url = request.getTargetUrl().toString(); + String methodName = request.getRequestMethod(); + HttpMethod httpMethod = null; + if ("GET".equals(methodName)) { + httpMethod = new GetMethod(url); + } + else if ("POST".equals(methodName)) { + httpMethod = new PostMethod(url); + } + else if ("PUT".equals(methodName)) { + httpMethod = new PutMethod(url); + } + else if ("DELETE".equals(methodName)) { + httpMethod = new DeleteMethod(url); + } + else if ("TRACE".equals(methodName)) { + httpMethod = new TraceMethod(url); + } + else if ("HEAD".equals(methodName)) { + httpMethod = new HeadMethod(url); + } + else if ("OPTIONS".equals(methodName)) { + httpMethod = new OptionsMethod(url); + } + else { + throw new UnsupportedOperationException("unsupported request method '" + methodName + "'"); + } + LocaleContext locale = LocaleContextHolder.getLocaleContext(); + if (locale != null) { + httpMethod.addRequestHeader(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale.getLocale())); + } + if (isAcceptGzipEncoding()) { + httpMethod.addRequestHeader(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP); + } + if (httpMethod instanceof EntityEnclosingMethod) { + String contentType = request.getContentType(); + if (contentType != null) { + httpMethod.addRequestHeader(HTTP_HEADER_CONTENT_TYPE, contentType); + } + } + return httpMethod; + } + + /** + * Set the given byte stream as the request body. + *
The default implementation simply sets the byte stream as the + * EntityEnclosingMethod's request body. This can be overridden, for + * example, to write a specific encoding and potentially set appropriate + * HTTP request headers. + * @param httpMethod the EntityEnclosingMethod on which to set the request body + * @param baos the ByteArrayOutputStream that contains the content + * @param contentType the request body's content type + * @throws IOException if thrown by I/O methods + * @see org.apache.commons.httpclient.methods.PostMethod#setRequestBody(java.io.InputStream) + * @see org.apache.commons.httpclient.methods.PostMethod#setRequestEntity + * @see org.apache.commons.httpclient.methods.InputStreamRequestEntity + */ + protected void setRequestBody( + EntityEnclosingMethod httpMethod, ByteArrayOutputStream baos, String contentType) + throws IOException { + httpMethod.setRequestEntity(new ByteArrayRequestEntity(baos.toByteArray(), contentType)); + } + + /** + * Execute the given HttpMethod instance. + * @param httpClient the HttpClient responsible for execution + * @param httpMethod the HttpMethod to be executed + * @throws IOException if thrown by I/O methods + * @see org.apache.commons.httpclient.HttpClient#executeMethod(org.apache.commons.httpclient.HttpMethod) + */ + private void executeHttpMethod(HttpClient httpClient, HttpMethod httpMethod) throws IOException { + httpClient.executeMethod(httpMethod); + } + + /** + * Validate the given response as contained in the HttpMethod object, + * throwing an exception if it does not correspond to a successful HTTP response. + *
This implementation rejects any HTTP status code beyond 2xx, to avoid + * parsing the response body and trying to read from a corrupted stream. + * @param httpMethod the executed HttpMethod to validate + * @throws IOException if validation failed + * @see org.apache.commons.httpclient.methods.PostMethod#getStatusCode() + * @see org.apache.commons.httpclient.HttpException + */ + private void validateResponse(HttpMethod httpMethod) throws IOException { + if (httpMethod.getStatusCode() >= 300) { + throw new HttpException( + "Did not receive successful HTTP response: status code = " + httpMethod.getStatusCode() + + ", status message = [" + httpMethod.getStatusText() + "]"); + } + } + + /** + * Extract the response body from the given executed request. + *
This implementation simply fetches the HttpMethod's response
+ * body stream. If the response is recognized as a GZIP response, the
+ * InputStream will be wrapped in a GZIPInputStream.
+ * @param httpMethod the HttpMethod from which to read the response body
+ * @return an InputStream for the response body, or null if no response stream is available
+ * @throws IOException if thrown by I/O methods
+ * @see #isGzipResponse
+ * @see java.util.zip.GZIPInputStream
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseBodyAsStream()
+ */
+ private InputStream readResponseBody(HttpMethod httpMethod) throws IOException {
+ byte[] responseBody = httpMethod.getResponseBody();
+ InputStream responseStream = null;
+ if (responseBody != null) {
+ responseStream = new ByteArrayInputStream(responseBody);
+ if (isGzipResponse(httpMethod)) {
+ responseStream = new GZIPInputStream(responseStream);
+ }
+ }
+ return responseStream;
+ }
+
+ /**
+ * Determine whether the given response indicates a GZIP response.
+ *
This implementation checks whether the HTTP "Content-Encoding" + * header contains "gzip" (in any casing). + * @param httpMethod the HttpMethod to check + * @return whether the given response indicates a GZIP response + * @see org.apache.commons.httpclient.HttpMethod#getResponseHeader(String) + */ + private boolean isGzipResponse(HttpMethod httpMethod) { + Header encodingHeader = httpMethod.getResponseHeader(HTTP_HEADER_CONTENT_ENCODING); + return (encodingHeader != null && encodingHeader.getValue() != null + && encodingHeader.getValue().toLowerCase().indexOf(ENCODING_GZIP) != -1); + } + +} diff --git a/org.springframework.integration.http/src/main/java/org/springframework/integration/http/SimpleHttpRequestExecutor.java b/org.springframework.integration.http/src/main/java/org/springframework/integration/http/SimpleHttpRequestExecutor.java index f90386c590..d5dc328936 100644 --- a/org.springframework.integration.http/src/main/java/org/springframework/integration/http/SimpleHttpRequestExecutor.java +++ b/org.springframework.integration.http/src/main/java/org/springframework/integration/http/SimpleHttpRequestExecutor.java @@ -32,7 +32,7 @@ import org.springframework.util.StringUtils; /** * Implementation of {@link HttpRequestExecutor} that uses {@link HttpURLConnection} * directly. This version has limited functionality but no additional dependencies. - * For more features, see {@link CommonsHttpRequestExecutor}. (TODO) + * For more features, see {@link CommonsHttpRequestExecutor}. * * @author Juergen Hoeller * @author Iwein Fuld diff --git a/org.springframework.integration.http/template.mf b/org.springframework.integration.http/template.mf index 6a83b7abd3..cce1ea3158 100644 --- a/org.springframework.integration.http/template.mf +++ b/org.springframework.integration.http/template.mf @@ -9,6 +9,7 @@ Import-Template: org.springframework.core.*;version="[2.5.6.A, 3.0.0)", org.springframework.util;version="[2.5.6.A, 3.0.0)", org.springframework.web.*;version="[2.5.6.A, 3.0.0)";resolution:=optional, + org.apache.commons.httpclient.*;version="[3.1.0, 4.0.0)", org.apache.commons.logging;version="[1.1.1, 2.0.0)", javax.servlet.*;version="[2.4.0, 3.0.0)";resolution:=optional Unversioned-Imports: