Author: lindner Date: Mon Nov 2 19:36:08 2009 New Revision: 832073 URL: http://svn.apache.org/viewvc?rev=832073&view=rev Log: SHINDIG-1215 | Modified Patch from chirag shah | Honor the maxObjSize in BasicHttpFetcher and make it configurable
Modified: incubator/shindig/trunk/java/common/conf/shindig.properties incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java Modified: incubator/shindig/trunk/java/common/conf/shindig.properties URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/conf/shindig.properties?rev=832073&r1=832072&r2=832073&view=diff ============================================================================== --- incubator/shindig/trunk/java/common/conf/shindig.properties (original) +++ incubator/shindig/trunk/java/common/conf/shindig.properties Mon Nov 2 19:36:08 2009 @@ -100,6 +100,13 @@ # if true, will only attempt to validate utf-8. Assumes all other encodings are ISO-8859-1. shindig.http.fast-encoding-detection=true +# Configuration for the HttpFetcher +# Connection timeout, in milliseconds, for requests. +shindig.http.client.connection-timeout-ms=5000 + +# Maximum size, in bytes, of the object we fetched, 0 == no limit +shindig.http.client.max-object-size-bytes=0 + # true to force strict content type checking for requests made to API endpoints. # E.g. require application/json for JSON-RPC shindig.api.disallow-unknown-content-types=true Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java?rev=832073&r1=832072&r2=832073&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java (original) +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java Mon Nov 2 19:36:08 2009 @@ -17,6 +17,7 @@ */ package org.apache.shindig.gadgets.http; +import com.google.inject.internal.Preconditions; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; @@ -31,10 +32,12 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; +import org.apache.commons.io.output.ByteArrayOutputStream; import com.google.common.collect.Maps; import com.google.inject.Inject; import com.google.inject.Singleton; +import com.google.inject.name.Named; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -59,38 +62,52 @@ @Singleton public class BasicHttpFetcher implements HttpFetcher { private static final int DEFAULT_CONNECT_TIMEOUT_MS = 5000; - private static final int DEFAULT_MAX_OBJECT_SIZE = 1024 * 1024; + private static final int DEFAULT_MAX_OBJECT_SIZE = 0; // no limit + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + // mutable fields must be volatile + private volatile int maxObjSize; private volatile int connectionTimeoutMs; /** * Creates a new fetcher for fetching HTTP objects. Not really suitable - * for production use. Someone should probably go and implement maxObjSize, - * for one thing. Use of an HTTP proxy for security is also necessary + * for production use. Use of an HTTP proxy for security is also necessary * for production deployment. * - * @param maxObjSize Maximum size, in bytes, of object to fetch. Except this - * isn't actually implemented. + * @param maxObjSize Maximum size, in bytes, of the object we will fetch, 0 if no limit.. * @param connectionTimeoutMs timeout, in milliseconds, for requests. */ public BasicHttpFetcher(int maxObjSize, int connectionTimeoutMs) { - this.connectionTimeoutMs = connectionTimeoutMs; + setMaxObjectSizeBytes(maxObjSize); + setConnectionTimeoutMs(connectionTimeoutMs); } /** - * Creates a new fetcher using the default maximum object size. + * Creates a new fetcher using the default maximum object size and timeout -- + * no limit and 5 seconds. */ - @Inject public BasicHttpFetcher() { this(DEFAULT_MAX_OBJECT_SIZE, DEFAULT_CONNECT_TIMEOUT_MS); } /** - * Change the connection timeout for fetches. + * Change the global maximum fetch size (in bytes) for all fetches. + * + * @param maxObjectSizeBytes value for maximum number of bytes, or 0 for no limit + */ + @Inject + public void setMaxObjectSizeBytes(@Named("shindig.http.client.max-object-size-bytes") int maxObjectSizeBytes) { + this.maxObjSize = maxObjectSizeBytes; + } + + /** + * Change the global connection timeout for all fetchs. * * @param connectionTimeoutMs new connection timeout in milliseconds */ - public void setConnectionTimeoutMs(int connectionTimeoutMs) { + @Inject(optional = true) + public void setConnectionTimeoutMs(@Named("shindig.http.client.connection-timeout-ms") int connectionTimeoutMs) { + Preconditions.checkArgument(connectionTimeoutMs > 0, "connection-timeout-ms must be greater than 0"); this.connectionTimeoutMs = connectionTimeoutMs; } @@ -140,10 +157,26 @@ is = new InflaterInputStream(responseBodyStream, inflater); } - byte[] body = IOUtils.toByteArray(is); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + int totalBytesRead = 0; + int currentBytesRead; + + while ((currentBytesRead = is.read(buffer)) != -1) { + output.write(buffer, 0, currentBytesRead); + totalBytesRead += currentBytesRead; + + if(maxObjSize > 0 && totalBytesRead > maxObjSize) { + IOUtils.closeQuietly(is); + IOUtils.closeQuietly(output); + // Exceeded max # of bytes + return HttpResponse.badrequest("Exceeded maximum number of bytes - " + this.maxObjSize); + } + } + return new HttpResponseBuilder() .setHttpStatusCode(responseCode) - .setResponse(body) + .setResponse(output.toByteArray()) .addHeaders(headers) .create(); } Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java?rev=832073&r1=832072&r2=832073&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java (original) +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponse.java Mon Nov 2 19:36:08 2009 @@ -185,6 +185,10 @@ return new HttpResponse(SC_INTERNAL_SERVER_ERROR, ""); } + public static HttpResponse badrequest(String msg) { + return new HttpResponse(SC_BAD_REQUEST, msg); + } + public static HttpResponse timeout() { return new HttpResponse(SC_GATEWAY_TIMEOUT, ""); }