From 0c9b3accda3da43766be9239ad9597a2fd873ff0 Mon Sep 17 00:00:00 2001 From: "adrian.f.cole" Date: Sun, 7 Jun 2009 11:06:29 +0000 Subject: [PATCH] Issue 52: warn when host header is used git-svn-id: http://jclouds.googlecode.com/svn/trunk@1083 3d8758e0-26b5-11de-8745-db77d3ebf521 --- .../jclouds/gae/URLFetchServiceClient.java | 241 ++++++++++-------- .../gae/URLFetchServiceClientTest.java | 216 ++++++++-------- 2 files changed, 233 insertions(+), 224 deletions(-) diff --git a/extensions/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java b/extensions/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java index 93abd85762..455df26cc5 100644 --- a/extensions/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java +++ b/extensions/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java @@ -24,135 +24,150 @@ package org.jclouds.gae; import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate; -import com.google.appengine.api.urlfetch.*; -import com.google.common.annotations.VisibleForTesting; -import com.google.inject.Inject; -import org.apache.commons.io.IOUtils; -import org.jclouds.http.*; -import org.jclouds.http.internal.BaseHttpFutureCommandClient; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.List; +import org.apache.commons.io.IOUtils; +import org.jclouds.http.HttpConstants; +import org.jclouds.http.HttpFutureCommand; +import org.jclouds.http.HttpFutureCommandClient; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.internal.BaseHttpFutureCommandClient; + +import com.google.appengine.api.urlfetch.HTTPHeader; +import com.google.appengine.api.urlfetch.HTTPMethod; +import com.google.appengine.api.urlfetch.HTTPRequest; +import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.common.annotations.VisibleForTesting; +import com.google.inject.Inject; + /** * Google App Engine version of {@link HttpFutureCommandClient} - * + * * @author Adrian Cole */ public class URLFetchServiceClient extends BaseHttpFutureCommandClient { - private final URLFetchService urlFetchService; + private final URLFetchService urlFetchService; - @Inject - public URLFetchServiceClient(URL target, URLFetchService urlFetchService) + @Inject + public URLFetchServiceClient(URL target, URLFetchService urlFetchService) throws MalformedURLException { - super(target); - this.urlFetchService = urlFetchService; - } + super(target); + this.urlFetchService = urlFetchService; + } - public void submit(HttpFutureCommand command) { - HttpRequest request = command.getRequest(); - HTTPResponse gaeResponse = null; - try { - for (HttpRequestFilter filter : requestFilters) { - filter.filter(request); - } - HttpResponse response = null; - for (; ;) { - logger.trace("%1$s - converting request %2$s", target, request); - HTTPRequest gaeRequest = convert(request); - if (logger.isTraceEnabled()) - logger.trace( - "%1$s - submitting request %2$s, headers: %3$s", - target, gaeRequest.getURL(), - headersAsString(gaeRequest.getHeaders())); - gaeResponse = this.urlFetchService.fetch(gaeRequest); - if (logger.isTraceEnabled()) - logger - .trace( - "%1$s - received response code %2$s, headers: %3$s", - target, gaeResponse.getResponseCode(), - headersAsString(gaeResponse.getHeaders())); - response = convert(gaeResponse); - int statusCode = response.getStatusCode(); - if (statusCode >= 500 && httpRetryHandler.retryRequest(command, response)) - continue; - break; - } - handleResponse(command, response); - } catch (Exception e) { - if (gaeResponse != null && gaeResponse.getContent() != null) { - logger.error(e, - "error encountered during the execution: %1$s%n%2$s", - gaeResponse, new String(gaeResponse.getContent())); - } - command.setException(e); - } - } + public void submit(HttpFutureCommand command) { + HttpRequest request = command.getRequest(); - String headersAsString(List headers) { - StringBuilder builder = new StringBuilder(""); - for (HTTPHeader header : headers) - builder.append("[").append(header.getName()).append("=").append( - header.getValue()).append("],"); - return builder.toString(); - } + HTTPResponse gaeResponse = null; + try { + for (HttpRequestFilter filter : requestFilters) { + filter.filter(request); + } + String hostHeader = request.getFirstHeaderOrNull(HttpConstants.HOST); + if (hostHeader != null) { + logger + .warn( + "Note that as of GAE SDK version 1.2.1, host headers are stripped. you passed %1$s", + hostHeader); + } + HttpResponse response = null; + for (;;) { + logger.trace("%1$s - converting request %2$s", target, request); + HTTPRequest gaeRequest = convert(request); + if (logger.isTraceEnabled()) + logger.trace("%1$s - submitting request %2$s, headers: %3$s", target, gaeRequest + .getURL(), headersAsString(gaeRequest.getHeaders())); + gaeResponse = this.urlFetchService.fetch(gaeRequest); + if (logger.isTraceEnabled()) + logger.info("%1$s - received response code %2$s, headers: %3$s", target, gaeResponse + .getResponseCode(), headersAsString(gaeResponse.getHeaders())); + response = convert(gaeResponse); + int statusCode = response.getStatusCode(); + if (statusCode >= 500 && httpRetryHandler.retryRequest(command, response)) + continue; + break; + } + handleResponse(command, response); + } catch (Exception e) { + if (gaeResponse != null && gaeResponse.getContent() != null) { + logger.error(e, "error encountered during the execution: %1$s%n%2$s", gaeResponse, + new String(gaeResponse.getContent())); + } + command.setException(e); + } + } - /** - * byte [] content is replayable and the only content type supportable by - * GAE. As such, we convert the original request content to a byte array. - */ - @VisibleForTesting - void changeRequestContentToBytes(HttpRequest request) throws IOException { - Object content = request.getPayload(); - if (content == null || content instanceof byte[]) { - return; - } else if (content instanceof String) { - String string = (String) content; - request.setPayload(string.getBytes()); - } else if (content instanceof InputStream || content instanceof File) { - InputStream i = content instanceof InputStream ? (InputStream) content - : new FileInputStream((File) content); - try { - request.setPayload(IOUtils.toByteArray(i)); - } finally { - IOUtils.closeQuietly(i); - } - } else { - throw new UnsupportedOperationException("Content not supported " - + content.getClass()); - } + String headersAsString(List headers) { + StringBuilder builder = new StringBuilder(""); + for (HTTPHeader header : headers) + builder.append("[").append(header.getName()).append("=").append(header.getValue()).append( + "],"); + return builder.toString(); + } - } + /** + * byte [] content is replayable and the only content type supportable by GAE. As such, we + * convert the original request content to a byte array. + */ + @VisibleForTesting + void changeRequestContentToBytes(HttpRequest request) throws IOException { + Object content = request.getPayload(); + if (content == null || content instanceof byte[]) { + return; + } else if (content instanceof String) { + String string = (String) content; + request.setPayload(string.getBytes()); + } else if (content instanceof InputStream || content instanceof File) { + InputStream i = content instanceof InputStream ? (InputStream) content + : new FileInputStream((File) content); + try { + request.setPayload(IOUtils.toByteArray(i)); + } finally { + IOUtils.closeQuietly(i); + } + } else { + throw new UnsupportedOperationException("Content not supported " + content.getClass()); + } - @VisibleForTesting - HttpResponse convert(HTTPResponse gaeResponse) { - HttpResponse response = new HttpResponse(); - response.setStatusCode(gaeResponse.getResponseCode()); - for (HTTPHeader header : gaeResponse.getHeaders()) { - response.getHeaders().put(header.getName(), header.getValue()); - } - if (gaeResponse.getContent() != null) { - response.setContent(new ByteArrayInputStream(gaeResponse - .getContent())); - } - return response; - } + } - @VisibleForTesting - HTTPRequest convert(HttpRequest request) throws IOException { - URL url = new URL(target, request.getUri()); - HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod - .valueOf(request.getMethod()), disallowTruncate()); - for (String header : request.getHeaders().keySet()) { - for (String value : request.getHeaders().get(header)) - gaeRequest.addHeader(new HTTPHeader(header, value)); - } - if (request.getPayload() != null) { - changeRequestContentToBytes(request); - gaeRequest.setPayload((byte[]) request.getPayload()); - } - return gaeRequest; - } + @VisibleForTesting + HttpResponse convert(HTTPResponse gaeResponse) { + HttpResponse response = new HttpResponse(); + response.setStatusCode(gaeResponse.getResponseCode()); + for (HTTPHeader header : gaeResponse.getHeaders()) { + response.getHeaders().put(header.getName(), header.getValue()); + } + if (gaeResponse.getContent() != null) { + response.setContent(new ByteArrayInputStream(gaeResponse.getContent())); + } + return response; + } + + @VisibleForTesting + HTTPRequest convert(HttpRequest request) throws IOException { + URL url = new URL(target, request.getUri()); + HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod.valueOf(request.getMethod()), + disallowTruncate().doNotFollowRedirects()); + for (String header : request.getHeaders().keySet()) { + for (String value : request.getHeaders().get(header)) + gaeRequest.addHeader(new HTTPHeader(header, value)); + } + if (request.getPayload() != null) { + changeRequestContentToBytes(request); + gaeRequest.setPayload((byte[]) request.getPayload()); + } + return gaeRequest; + } } diff --git a/extensions/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java b/extensions/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java index 01f5c39046..4a4a24493b 100644 --- a/extensions/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java +++ b/extensions/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java @@ -57,129 +57,123 @@ import com.google.appengine.api.urlfetch.URLFetchService; */ @Test public class URLFetchServiceClientTest { - URLFetchServiceClient client; - URL url; + URLFetchServiceClient client; + URL url; - @BeforeTest - void setupClient() throws MalformedURLException { - url = new URL("http://localhost:80"); - client = new URLFetchServiceClient(url, - createNiceMock(URLFetchService.class)); - } + @BeforeTest + void setupClient() throws MalformedURLException { + url = new URL("http://localhost:80"); + client = new URLFetchServiceClient(url, createNiceMock(URLFetchService.class)); + } - @Test - void testConvertWithHeaders() { - HTTPResponse gaeResponse = createMock(HTTPResponse.class); - expect(gaeResponse.getResponseCode()).andReturn(200); - List headers = new ArrayList(); - headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml")); - expect(gaeResponse.getHeaders()).andReturn(headers); - expect(gaeResponse.getContent()).andReturn(null).atLeastOnce(); - replay(gaeResponse); - HttpResponse response = client.convert(gaeResponse); - assertEquals(response.getStatusCode(), 200); - assertEquals(response.getContent(), null); - assertEquals(response.getHeaders().size(), 1); - assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), - "text/xml"); - } + @Test + void testConvertWithHeaders() { + HTTPResponse gaeResponse = createMock(HTTPResponse.class); + expect(gaeResponse.getResponseCode()).andReturn(200); + List headers = new ArrayList(); + headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml")); + expect(gaeResponse.getHeaders()).andReturn(headers); + expect(gaeResponse.getContent()).andReturn(null).atLeastOnce(); + replay(gaeResponse); + HttpResponse response = client.convert(gaeResponse); + assertEquals(response.getStatusCode(), 200); + assertEquals(response.getContent(), null); + assertEquals(response.getHeaders().size(), 1); + assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), "text/xml"); + } - @Test - void testConvertWithContent() throws IOException { - HTTPResponse gaeResponse = createMock(HTTPResponse.class); - expect(gaeResponse.getResponseCode()).andReturn(200); - List headers = new ArrayList(); - headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml")); - expect(gaeResponse.getHeaders()).andReturn(headers); - expect(gaeResponse.getContent()).andReturn("hello".getBytes()) - .atLeastOnce(); - replay(gaeResponse); - HttpResponse response = client.convert(gaeResponse); - assertEquals(response.getStatusCode(), 200); - assertEquals(IOUtils.toString(response.getContent()), "hello"); - assertEquals(response.getHeaders().size(), 1); - assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), - "text/xml"); - } + @Test + void testConvertWithContent() throws IOException { + HTTPResponse gaeResponse = createMock(HTTPResponse.class); + expect(gaeResponse.getResponseCode()).andReturn(200); + List headers = new ArrayList(); + headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml")); + expect(gaeResponse.getHeaders()).andReturn(headers); + expect(gaeResponse.getContent()).andReturn("hello".getBytes()).atLeastOnce(); + replay(gaeResponse); + HttpResponse response = client.convert(gaeResponse); + assertEquals(response.getStatusCode(), 200); + assertEquals(IOUtils.toString(response.getContent()), "hello"); + assertEquals(response.getHeaders().size(), 1); + assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), "text/xml"); + } - @Test - void testConvertRequestGetsTargetAndUri() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - HTTPRequest gaeRequest = client.convert(request); - assertEquals(gaeRequest.getURL().getPath(), "/foo"); - } + @Test + void testConvertRequestGetsTargetAndUri() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + HTTPRequest gaeRequest = client.convert(request); + assertEquals(gaeRequest.getURL().getPath(), "/foo"); + } - @Test - void testConvertRequestSetsFetchOptions() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - HTTPRequest gaeRequest = client.convert(request); - assert gaeRequest.getFetchOptions() != null; - } + @Test + void testConvertRequestSetsFetchOptions() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + HTTPRequest gaeRequest = client.convert(request); + assert gaeRequest.getFetchOptions() != null; + } - @Test - void testConvertRequestSetsHeaders() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - request.getHeaders().put("foo", "bar"); - HTTPRequest gaeRequest = client.convert(request); - assertEquals(gaeRequest.getHeaders().get(0).getName(), "foo"); - assertEquals(gaeRequest.getHeaders().get(0).getValue(), "bar"); - } + @Test + void testConvertRequestSetsHeaders() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + request.getHeaders().put("foo", "bar"); + HTTPRequest gaeRequest = client.convert(request); + assertEquals(gaeRequest.getHeaders().get(0).getName(), "foo"); + assertEquals(gaeRequest.getHeaders().get(0).getValue(), "bar"); + } - @Test - void testConvertRequestNoContent() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - HTTPRequest gaeRequest = client.convert(request); - assert gaeRequest.getPayload() == null; - assertEquals(gaeRequest.getHeaders().size(), 0); - } + @Test + void testConvertRequestNoContent() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + HTTPRequest gaeRequest = client.convert(request); + assert gaeRequest.getPayload() == null; + assertEquals(gaeRequest.getHeaders().size(), 0); + } - @Test - void testConvertRequestStringContent() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - request.setPayload("hoot!"); - testHoot(request); - } + @Test + void testConvertRequestStringContent() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + request.setPayload("hoot!"); + testHoot(request); + } - @Test - void testConvertRequestInputStreamContent() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - request.setPayload(IOUtils.toInputStream("hoot!")); - testHoot(request); - } + @Test + void testConvertRequestInputStreamContent() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + request.setPayload(IOUtils.toInputStream("hoot!")); + testHoot(request); + } - @Test - void testConvertRequestBytesContent() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - request.setPayload("hoot!".getBytes()); - testHoot(request); - } + @Test + void testConvertRequestBytesContent() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + request.setPayload("hoot!".getBytes()); + testHoot(request); + } - @Test(expectedExceptions = UnsupportedOperationException.class) - void testConvertRequestBadContent() throws IOException { - HttpRequest request = new HttpRequest("GET", "foo"); - request.setPayload(new Date()); - client.convert(request); + @Test(expectedExceptions = UnsupportedOperationException.class) + void testConvertRequestBadContent() throws IOException { + HttpRequest request = new HttpRequest("GET", "foo"); + request.setPayload(new Date()); + client.convert(request); - } + } - @Test - @Parameters("basedir") - void testConvertRequestFileContent(String basedir) throws IOException { - File file = new File(basedir, "target/testfiles/hoot"); - file.getParentFile().mkdirs(); - IOUtils.write("hoot!", new FileOutputStream(file)); - HttpRequest request = new HttpRequest("GET", "foo"); - request.setPayload(file); - testHoot(request); - } - - private void testHoot(HttpRequest request) throws IOException { - request.getHeaders().put(HttpHeaders.CONTENT_TYPE,"text/plain"); - HTTPRequest gaeRequest = client.convert(request); - assertEquals(gaeRequest.getHeaders().get(0).getName(), - HttpHeaders.CONTENT_TYPE); - assertEquals(gaeRequest.getHeaders().get(0).getValue(), "text/plain"); - assertEquals(new String(gaeRequest.getPayload()), "hoot!"); - } + @Test + @Parameters("basedir") + void testConvertRequestFileContent(String basedir) throws IOException { + File file = new File(basedir, "target/testfiles/hoot"); + file.getParentFile().mkdirs(); + IOUtils.write("hoot!", new FileOutputStream(file)); + HttpRequest request = new HttpRequest("GET", "foo"); + request.setPayload(file); + testHoot(request); + } + private void testHoot(HttpRequest request) throws IOException { + request.getHeaders().put(HttpHeaders.CONTENT_TYPE, "text/plain"); + HTTPRequest gaeRequest = client.convert(request); + assertEquals(gaeRequest.getHeaders().get(0).getName(), HttpHeaders.CONTENT_TYPE); + assertEquals(gaeRequest.getHeaders().get(0).getValue(), "text/plain"); + assertEquals(new String(gaeRequest.getPayload()), "hoot!"); + } }