From 19ec0dbdd10fd940f9fb88399a0afa92cf41d560 Mon Sep 17 00:00:00 2001 From: Gabe Ki Date: Wed, 11 Feb 2015 14:31:52 -0800 Subject: [PATCH 1/2] Add redirection for 301 - Issue #147 --- .../dockerjava/core/DockerClientConfig.java | 22 +++++++++-- .../core/util/FollowRedirectsFilter.java | 37 +++++++++++++++++++ .../util/ResponseStatusExceptionFilter.java | 1 - .../jaxrs/DockerCmdExecFactoryImpl.java | 5 +++ 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index 7513c7f29..f4881c194 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -33,6 +33,7 @@ public class DockerClientConfig implements Serializable { private static final String DOCKER_IO_READ_TIMEOUT_PROPERTY = "docker.io.readTimeout"; // this is really confusing, as there are two ways to spell it private static final String DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY = "docker.io.enableLoggingFilter"; + private static final String DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY = "docker.io.followRedirectsFilterEnabled"; private static final String DOCKER_IO_DOCKER_CERT_PATH_PROPERTY = "docker.io.dockerCertPath"; private static final String DOCKER_IO_DOCKER_CFG_PATH_PROPERTY = "docker.io.dockerCfgPath"; // connection pooling properties @@ -53,6 +54,7 @@ public class DockerClientConfig implements Serializable { m.put("DOCKER_SERVER_ADDRESS", DOCKER_IO_SERVER_ADDRESS_PROPERTY); m.put("DOCKER_READ_TIMEOUT", DOCKER_IO_READ_TIMEOUT_PROPERTY); m.put("DOCKER_LOGGING_FILTER_ENABLED", DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY); + m.put("DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY", DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY); m.put(DOCKER_CERT_PATH_PROPERTY, DOCKER_IO_DOCKER_CERT_PATH_PROPERTY); m.put("DOCKER_CFG_PATH", DOCKER_IO_DOCKER_CFG_PATH_PROPERTY); ENV_NAME_TO_IO_NAME = Collections.unmodifiableMap(m); @@ -63,14 +65,15 @@ public class DockerClientConfig implements Serializable { private final String version, username, password, email, serverAddress, dockerCfgPath; private final Integer readTimeout; private final boolean loggingFilterEnabled; + private final boolean followRedirectsFilterEnabled; private final SSLConfig sslConfig; private final int maxTotalConnections; private final int maxPerRouteConnections; DockerClientConfig(URI uri, String version, String username, String password, String email, String serverAddress, - String dockerCfgPath, Integer readTimeout, boolean loggingFilterEnabled, SSLConfig sslConfig, - int maxTotalConns, int maxPerRouteConns) { + String dockerCfgPath, Integer readTimeout, boolean loggingFilterEnabled, boolean followRedirectsFilterEnabled, + SSLConfig sslConfig, int maxTotalConns, int maxPerRouteConns) { this.uri = uri; this.version = version; this.username = username; @@ -80,6 +83,7 @@ public class DockerClientConfig implements Serializable { this.dockerCfgPath = dockerCfgPath; this.readTimeout = readTimeout; this.loggingFilterEnabled = loggingFilterEnabled; + this.followRedirectsFilterEnabled = followRedirectsFilterEnabled; this.sslConfig = sslConfig; this.maxTotalConnections = maxTotalConns; this.maxPerRouteConnections = maxPerRouteConns; @@ -243,6 +247,10 @@ public boolean isLoggingFilterEnabled() { return loggingFilterEnabled; } + public boolean followRedirectsFilterEnabled() { + return followRedirectsFilterEnabled; + } + public SSLConfig getSslConfig() { return sslConfig; } @@ -345,6 +353,7 @@ public String toString() { ", sslConfig='" + sslConfig + '\'' + ", readTimeout=" + readTimeout + ", loggingFilterEnabled=" + loggingFilterEnabled + + ", followRedirectsFilterEnabled=" + followRedirectsFilterEnabled + '}'; } @@ -352,7 +361,7 @@ public static class DockerClientConfigBuilder { private URI uri; private String version, username, password, email, serverAddress, dockerCfgPath; private Integer readTimeout, maxTotalConnections, maxPerRouteConnections; - private boolean loggingFilterEnabled; + private boolean loggingFilterEnabled, followRedirectsFilterEnabled; private SSLConfig sslConfig; /** @@ -370,6 +379,7 @@ public DockerClientConfigBuilder withProperties(Properties p) { .withServerAddress(p.getProperty(DOCKER_IO_SERVER_ADDRESS_PROPERTY)) .withReadTimeout(Integer.valueOf(p.getProperty(DOCKER_IO_READ_TIMEOUT_PROPERTY, "0"))) .withLoggingFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY, "true"))) + .withFollowRedirectsFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY, "true"))) .withDockerCertPath(p.getProperty(DOCKER_IO_DOCKER_CERT_PATH_PROPERTY)) .withDockerCfgPath(p.getProperty(DOCKER_IO_DOCKER_CFG_PATH_PROPERTY)) .withMaxPerRouteConnections(Integer.valueOf(p.getProperty(DOCKER_IO_MAX_PER_ROUTE_PROPERTY, "2"))) @@ -428,6 +438,11 @@ public final DockerClientConfigBuilder withLoggingFilter(boolean loggingFilterEn return this; } + public final DockerClientConfigBuilder withFollowRedirectsFilter(boolean followRedirectsFilterEnabled) { + this.followRedirectsFilterEnabled = followRedirectsFilterEnabled; + return this; + } + public final DockerClientConfigBuilder withDockerCertPath(String dockerCertPath) { this.sslConfig = new LocalDirectorySSLConfig(dockerCertPath); return this; @@ -455,6 +470,7 @@ public DockerClientConfig build() { dockerCfgPath, readTimeout, loggingFilterEnabled, + followRedirectsFilterEnabled, sslConfig, maxTotalConnections, maxPerRouteConnections diff --git a/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java b/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java new file mode 100644 index 000000000..fd375eceb --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java @@ -0,0 +1,37 @@ +package com.github.dockerjava.core.util; + +import java.io.IOException; +import java.io.InputStream; + +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.core.Response; + +/** + * Default implementation of RedirectStrategy honors the restrictions + * on automatic redirection of entity enclosing methods such as POST + * and PUT imposed by the HTTP specification. 302 Moved Temporarily, + * 301 Moved Permanently and 307 Temporary Redirect status codes will + * result in an automatic redirect of HEAD and GET methods only. + * + * {@link org.apache.http.impl.client.DefaultRedirectStrategy} + * + * This filter allows arbitrary redirection for other methods. + */ +public class FollowRedirectsFilter implements ClientResponseFilter { + + @Override + public void filter(ClientRequestContext requestContext, + ClientResponseContext responseContext) throws IOException { + if (!responseContext.getStatusInfo().getFamily().equals(Response.Status.Family.REDIRECTION)) { + return; + } + + Response resp = requestContext.getClient().target(responseContext.getLocation()) + .request().method(requestContext.getMethod()); + responseContext.setEntityStream((InputStream) resp.getEntity()); + responseContext.setStatusInfo(resp.getStatusInfo()); + responseContext.setStatus(resp.getStatus()); + } +} diff --git a/src/main/java/com/github/dockerjava/core/util/ResponseStatusExceptionFilter.java b/src/main/java/com/github/dockerjava/core/util/ResponseStatusExceptionFilter.java index 99893a429..7e9708564 100644 --- a/src/main/java/com/github/dockerjava/core/util/ResponseStatusExceptionFilter.java +++ b/src/main/java/com/github/dockerjava/core/util/ResponseStatusExceptionFilter.java @@ -37,7 +37,6 @@ public void filter(ClientRequestContext requestContext, ClientResponseContext re case 200: case 201: case 204: - case 301: return; case 304: throw new NotModifiedException(getBodyAsMessage(responseContext)); diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 4edba9fcb..4652b4b99 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -6,6 +6,7 @@ import java.net.URI; import com.github.dockerjava.api.command.*; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,6 +29,7 @@ import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import com.github.dockerjava.api.DockerClientException; import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.util.FollowRedirectsFilter; import com.github.dockerjava.core.util.JsonClientFilter; import com.github.dockerjava.core.util.ResponseStatusExceptionFilter; import com.github.dockerjava.core.util.SelectiveLoggingFilter; @@ -49,6 +51,9 @@ public void init(DockerClientConfig dockerClientConfig) { clientConfig.register(ResponseStatusExceptionFilter.class); clientConfig.register(JsonClientFilter.class); clientConfig.register(JacksonJsonProvider.class); + if (dockerClientConfig.followRedirectsFilterEnabled()) { + clientConfig.register(FollowRedirectsFilter.class); + } if (dockerClientConfig.isLoggingFilterEnabled()) { clientConfig.register(new SelectiveLoggingFilter(LOGGER, true)); From adb85a84ca0ea94d246e3d4d8000136ef7d3dffd Mon Sep 17 00:00:00 2001 From: Gabe Ki Date: Wed, 11 Feb 2015 15:13:47 -0800 Subject: [PATCH 2/2] fix unit tests --- .../dockerjava/core/DockerClientConfig.java | 7 ++++--- .../core/util/FollowRedirectsFilter.java | 18 +++++++++--------- .../jaxrs/DockerCmdExecFactoryImpl.java | 6 +++--- .../core/DockerClientConfigTest.java | 4 ++-- .../dockerjava/core/DockerClientImplTest.java | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java index f4881c194..6b87a927a 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientConfig.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientConfig.java @@ -33,7 +33,7 @@ public class DockerClientConfig implements Serializable { private static final String DOCKER_IO_READ_TIMEOUT_PROPERTY = "docker.io.readTimeout"; // this is really confusing, as there are two ways to spell it private static final String DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY = "docker.io.enableLoggingFilter"; - private static final String DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY = "docker.io.followRedirectsFilterEnabled"; + private static final String DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY = "docker.io.followRedirectsFilter"; private static final String DOCKER_IO_DOCKER_CERT_PATH_PROPERTY = "docker.io.dockerCertPath"; private static final String DOCKER_IO_DOCKER_CFG_PATH_PROPERTY = "docker.io.dockerCfgPath"; // connection pooling properties @@ -54,7 +54,7 @@ public class DockerClientConfig implements Serializable { m.put("DOCKER_SERVER_ADDRESS", DOCKER_IO_SERVER_ADDRESS_PROPERTY); m.put("DOCKER_READ_TIMEOUT", DOCKER_IO_READ_TIMEOUT_PROPERTY); m.put("DOCKER_LOGGING_FILTER_ENABLED", DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY); - m.put("DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY", DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY); + m.put("DOCKER_FOLLOW_REDIRECTS_FILTER_ENABLED", DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY); m.put(DOCKER_CERT_PATH_PROPERTY, DOCKER_IO_DOCKER_CERT_PATH_PROPERTY); m.put("DOCKER_CFG_PATH", DOCKER_IO_DOCKER_CFG_PATH_PROPERTY); ENV_NAME_TO_IO_NAME = Collections.unmodifiableMap(m); @@ -186,6 +186,7 @@ private static Properties overrideDockerPropertiesWithSystemProperties(Propertie DOCKER_IO_SERVER_ADDRESS_PROPERTY, DOCKER_IO_READ_TIMEOUT_PROPERTY, DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY, + DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY, DOCKER_IO_DOCKER_CERT_PATH_PROPERTY, DOCKER_IO_DOCKER_CFG_PATH_PROPERTY, }) { @@ -379,7 +380,7 @@ public DockerClientConfigBuilder withProperties(Properties p) { .withServerAddress(p.getProperty(DOCKER_IO_SERVER_ADDRESS_PROPERTY)) .withReadTimeout(Integer.valueOf(p.getProperty(DOCKER_IO_READ_TIMEOUT_PROPERTY, "0"))) .withLoggingFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_ENABLE_LOGGING_FILTER_PROPERTY, "true"))) - .withFollowRedirectsFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY, "true"))) + .withFollowRedirectsFilter(Boolean.valueOf(p.getProperty(DOCKER_IO_FOLLOW_REDIRECTS_FILTER_PROPERTY, "false"))) .withDockerCertPath(p.getProperty(DOCKER_IO_DOCKER_CERT_PATH_PROPERTY)) .withDockerCfgPath(p.getProperty(DOCKER_IO_DOCKER_CFG_PATH_PROPERTY)) .withMaxPerRouteConnections(Integer.valueOf(p.getProperty(DOCKER_IO_MAX_PER_ROUTE_PROPERTY, "2"))) diff --git a/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java b/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java index fd375eceb..b4431b1f4 100644 --- a/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java +++ b/src/main/java/com/github/dockerjava/core/util/FollowRedirectsFilter.java @@ -21,17 +21,17 @@ */ public class FollowRedirectsFilter implements ClientResponseFilter { - @Override + @Override public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { - if (!responseContext.getStatusInfo().getFamily().equals(Response.Status.Family.REDIRECTION)) { - return; - } + if (!responseContext.getStatusInfo().getFamily().equals(Response.Status.Family.REDIRECTION)) { + return; + } - Response resp = requestContext.getClient().target(responseContext.getLocation()) - .request().method(requestContext.getMethod()); - responseContext.setEntityStream((InputStream) resp.getEntity()); - responseContext.setStatusInfo(resp.getStatusInfo()); - responseContext.setStatus(resp.getStatus()); + Response resp = requestContext.getClient().target(responseContext.getLocation()) + .request().method(requestContext.getMethod()); + responseContext.setEntityStream((InputStream) resp.getEntity()); + responseContext.setStatusInfo(resp.getStatusInfo()); + responseContext.setStatus(resp.getStatus()); } } diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 4652b4b99..5bff4c661 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -48,12 +48,12 @@ public void init(DockerClientConfig dockerClientConfig) { clientConfig.connectorProvider(new ApacheConnectorProvider()); clientConfig.property(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); - clientConfig.register(ResponseStatusExceptionFilter.class); - clientConfig.register(JsonClientFilter.class); - clientConfig.register(JacksonJsonProvider.class); if (dockerClientConfig.followRedirectsFilterEnabled()) { clientConfig.register(FollowRedirectsFilter.class); } + clientConfig.register(ResponseStatusExceptionFilter.class); + clientConfig.register(JsonClientFilter.class); + clientConfig.register(JacksonJsonProvider.class); if (dockerClientConfig.isLoggingFilterEnabled()) { clientConfig.register(new SelectiveLoggingFilter(LOGGER, true)); diff --git a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java index 4611f4307..64ab912d0 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java +++ b/src/test/java/com/github/dockerjava/core/DockerClientConfigTest.java @@ -16,12 +16,12 @@ public class DockerClientConfigTest { public static final DockerClientConfig EXAMPLE_CONFIG = newExampleConfig(); private static DockerClientConfig newExampleConfig() { - return new DockerClientConfig(URI.create("http://foo"), "bar", "baz", "qux", "blam", "wham", "flam", 877, false, new LocalDirectorySSLConfig("flim"), 20, 2); + return new DockerClientConfig(URI.create("http://foo"), "bar", "baz", "qux", "blam", "wham", "flam", 877, false, false, new LocalDirectorySSLConfig("flim"), 20, 2); } @Test public void string() throws Exception { - assertEquals("DockerClientConfig{uri=http://foo, version='bar', username='baz', password='qux', email='blam', serverAddress='wham', dockerCfgPath='flam', sslConfig='LocalDirectorySSLConfig{dockerCertPath=flim}', readTimeout=877, loggingFilterEnabled=false}", + assertEquals("DockerClientConfig{uri=http://foo, version='bar', username='baz', password='qux', email='blam', serverAddress='wham', dockerCfgPath='flam', sslConfig='LocalDirectorySSLConfig{dockerCertPath=flim}', readTimeout=877, loggingFilterEnabled=false, followRedirectsFilterEnabled=false}", EXAMPLE_CONFIG.toString()); } diff --git a/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java b/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java index 1f5604fe8..2a961e3b8 100644 --- a/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java +++ b/src/test/java/com/github/dockerjava/core/DockerClientImplTest.java @@ -10,7 +10,7 @@ public class DockerClientImplTest { @Test public void configuredInstanceAuthConfig() throws Exception { // given a config with null serverAddress - DockerClientConfig dockerClientConfig = new DockerClientConfig(null, null, "", "", "", null, null, 0, false, null, 20, 2); + DockerClientConfig dockerClientConfig = new DockerClientConfig(null, null, "", "", "", null, null, 0, false, false, null, 20, 2); DockerClientImpl dockerClient = DockerClientImpl.getInstance(dockerClientConfig); // when we get the auth config