Repository: jclouds Updated Branches: refs/heads/master f832ad00a -> 07e64a2d0
Allow to globally configure the 'Connection: close' header Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/07e64a2d Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/07e64a2d Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/07e64a2d Branch: refs/heads/master Commit: 07e64a2d0743b8925887ac802cec648befdc112f Parents: f832ad0 Author: Ignasi Barrera <[email protected]> Authored: Fri Oct 2 15:15:41 2015 +0200 Committer: Ignasi Barrera <[email protected]> Committed: Fri Oct 2 15:44:24 2015 +0200 ---------------------------------------------------------------------- core/src/main/java/org/jclouds/Constants.java | 6 ++++ .../jclouds/apis/internal/BaseApiMetadata.java | 2 ++ .../http/filters/ConnectionCloseHeader.java | 33 +++++++++++++++++ .../rest/internal/RestAnnotationProcessor.java | 10 +++++- .../http/filters/ConnectionCloseHeaderTest.java | 38 ++++++++++++++++++++ .../internal/RestAnnotationProcessorTest.java | 29 +++++++++++++++ 6 files changed, 117 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/Constants.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/Constants.java b/core/src/main/java/org/jclouds/Constants.java index a658026..115edf1 100644 --- a/core/src/main/java/org/jclouds/Constants.java +++ b/core/src/main/java/org/jclouds/Constants.java @@ -308,6 +308,12 @@ public final class Constants { public static final String PROPERTY_STRIP_EXPECT_HEADER = "jclouds.strip-expect-header"; /** + * When true, add the Connection: close header. Useful when interacting with + * providers that don't properly support persistent connections. Defaults to false. + */ + public static final String PROPERTY_CONNECTION_CLOSE_HEADER = "jclouds.connection-close-header"; + + /** * The maximum number of blob deletes happening in parallel at any point in time. */ public static final String PROPERTY_MAX_PARALLEL_DELETES = "jclouds.max-parallel-deletes"; http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java b/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java index 7b5ff35..1cfbb6f 100644 --- a/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java +++ b/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java @@ -18,6 +18,7 @@ package org.jclouds.apis.internal; import static com.google.common.base.Objects.equal; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.Constants.PROPERTY_CONNECTION_CLOSE_HEADER; import static org.jclouds.Constants.PROPERTY_CONNECTION_TIMEOUT; import static org.jclouds.Constants.PROPERTY_ISO3166_CODES; import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT; @@ -73,6 +74,7 @@ public abstract class BaseApiMetadata implements ApiMetadata { props.setProperty(PROPERTY_SESSION_INTERVAL, 60 + ""); props.setProperty(PROPERTY_PRETTY_PRINT_PAYLOADS, "true"); props.setProperty(PROPERTY_STRIP_EXPECT_HEADER, "false"); + props.setProperty(PROPERTY_CONNECTION_CLOSE_HEADER, "false"); // By default, we allow maximum parallel deletes to be equal to the number // of user threads since one thread is used to delete on blob. http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java b/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java new file mode 100644 index 0000000..ba2b55c --- /dev/null +++ b/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jclouds.http.filters; + +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; + +import com.google.common.net.HttpHeaders; +import com.google.inject.Singleton; + +@Singleton +public class ConnectionCloseHeader implements HttpRequestFilter { + @Override + public HttpRequest filter(HttpRequest request) throws HttpException { + return request.toBuilder().addHeader(HttpHeaders.CONNECTION, "close").build(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index 74b1ac1..f6ebc8c 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -51,6 +51,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; + import javax.annotation.Resource; import javax.inject.Named; import javax.ws.rs.FormParam; @@ -65,6 +66,7 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; import org.jclouds.http.Uris.UriBuilder; +import org.jclouds.http.filters.ConnectionCloseHeader; import org.jclouds.http.filters.StripExpectHeader; import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.io.ContentMetadataCodec; @@ -147,12 +149,14 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest private final GetAcceptHeaders getAcceptHeaders; private final Invocation caller; private final boolean stripExpectHeader; + private final boolean connectionCloseHeader; @Inject private RestAnnotationProcessor(Injector injector, @ApiVersion String apiVersion, @BuildVersion String buildVersion, HttpUtils utils, ContentMetadataCodec contentMetadataCodec, InputParamValidator inputParamValidator, GetAcceptHeaders getAcceptHeaders, @Nullable @Named("caller") Invocation caller, - @Named(Constants.PROPERTY_STRIP_EXPECT_HEADER) boolean stripExpectHeader) { + @Named(Constants.PROPERTY_STRIP_EXPECT_HEADER) boolean stripExpectHeader, + @Named(Constants.PROPERTY_CONNECTION_CLOSE_HEADER) boolean connectionCloseHeader) { this.injector = injector; this.utils = utils; this.contentMetadataCodec = contentMetadataCodec; @@ -162,6 +166,7 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest this.getAcceptHeaders = getAcceptHeaders; this.caller = caller; this.stripExpectHeader = stripExpectHeader; + this.connectionCloseHeader = connectionCloseHeader; } /** @@ -211,6 +216,9 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest if (stripExpectHeader) { requestBuilder.filter(new StripExpectHeader()); } + if (connectionCloseHeader) { + requestBuilder.filter(new ConnectionCloseHeader()); + } Multimap<String, Object> tokenValues = LinkedHashMultimap.create(); http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java b/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java new file mode 100644 index 0000000..342b14c --- /dev/null +++ b/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jclouds.http.filters; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import org.jclouds.http.HttpRequest; +import org.testng.annotations.Test; + +import com.google.common.net.HttpHeaders; + +@Test(groups = "unit") +public class ConnectionCloseHeaderTest { + public void testConnectionHeaderIsAdded() { + HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build(); + request = new ConnectionCloseHeader().filter(request); + + assertTrue(request.getHeaders().containsKey(HttpHeaders.CONNECTION)); + assertEquals(request.getHeaders().get(HttpHeaders.CONNECTION).size(), 1); + assertEquals(request.getHeaders().get(HttpHeaders.CONNECTION).iterator().next(), "close"); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java index 40e8f83..7e43551 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -78,6 +78,7 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpResponse; import org.jclouds.http.IOExceptionRetryHandler; +import org.jclouds.http.filters.ConnectionCloseHeader; import org.jclouds.http.filters.StripExpectHeader; import org.jclouds.http.functions.ParseFirstJsonValueNamed; import org.jclouds.http.functions.ParseJson; @@ -1440,6 +1441,34 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(request.getFilters().get(1).getClass(), StripExpectHeader.class); } + @Test + public void testRequestFilterAddConnection() { + // First, verify that by default, the StripExpectHeader filter is not applied + Invokable<?, ?> method = method(TestRequestFilter.class, "post"); + Invocation invocation = Invocation.create(method, + ImmutableList.<Object>of(HttpRequest.builder().method("POST").endpoint("http://localhost").build())); + GeneratedHttpRequest request = processor.apply(invocation); + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), TestRequestFilter1.class); + + // Now let's create a new injector with the property set. Use that to create the annotation processor. + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_CONNECTION_CLOSE_HEADER, "true"); + Injector injector = ContextBuilder.newBuilder(forApiOnEndpoint(Callee.class, "http://localhost:9999")) + .modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() { + protected void configure() { + bind(new TypeLiteral<Supplier<URI>>() { + }).annotatedWith(Localhost2.class).toInstance( + Suppliers.ofInstance(URI.create("http://localhost:1111"))); + }})) + .overrides(overrides).buildInjector(); + RestAnnotationProcessor newProcessor = injector.getInstance(RestAnnotationProcessor.class); + // Verify that this time the filter is indeed applied as expected. + request = newProcessor.apply(invocation); + assertEquals(request.getFilters().size(), 2); + assertEquals(request.getFilters().get(1).getClass(), ConnectionCloseHeader.class); + } + public class TestEncoding { @GET @Path("/{path1}/{path2}")
