Skip to content

Added a way to provide custom HTTP features (included: BasicAuthentication)#222

Closed
ericfjosne wants to merge 8 commits intodocker-java:masterfrom
ericfjosne:http-features
Closed

Added a way to provide custom HTTP features (included: BasicAuthentication)#222
ericfjosne wants to merge 8 commits intodocker-java:masterfrom
ericfjosne:http-features

Conversation

@ericfjosne
Copy link
Copy Markdown

I needed to add BasicAuthentication for the calls to the API.

This pull request allows an optional custom list of AbstractHttpFeatures to be given to the DockerClientBuilder.getInstance method. It also implements the HttpBasicAuthenticationFeature class I needed.

This branch is based on today's (13/05/2015) master branch from the main repo.

efj and others added 8 commits March 3, 2015 15:58
Required when creating an image with a FROM command, using a private
registry.
Removed basic auth parameters from DockerClientConfig.
Created first AbstractHttpFeature: HttpBasicAuthenticationFeature.
Conflicts:
	src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java
	src/main/java/com/github/dockerjava/core/DockerClientImpl.java
	src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java
	src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java
	src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java
@marcuslinke
Copy link
Copy Markdown
Contributor

@ericfjosne I've pushed a branch 'refact-config' (#226) where I've factored out all JAXRS/ApacheConnector implementation specific parameters from DockerClientConfig. These and any additional ClientResponseFilters can be configured then via DockerCmdExecFactoryImpl directly.

Please take a look at it to see if you could implement your use case this way. Any comments are really welcome. Thanks!

@ericfjosne
Copy link
Copy Markdown
Author

Good morning Marcus,

Sorry for the long delay. I only had the chance to take a look at your suggestions tonight.
Thanks for your support on this matter, and the suggested implementation.

For the reminder, my fork added the 3 following features to your project:

Basic HTTP authentication on the docker API
Connect timeout parametrized configuration
Buffered request, which allow the HTTP request to be “replayed" if needed.

The ClientResponseFilters only applies after the communication is performed, while I needed something to adapt it beforehand.
My use case requires not a ClientResponseFilter but a ClientRequestFilter instead.

I tweaked your branch code (refact-config) a bit and managed to get it all working for me. Here is what I changed:

In your DockerCmdExecFactoryImpl, i changed the following:

private ClientRequestFilter[] clientRequestFilters; // instead of Class<? extends ClientResponseFilter>[] clientResponseFilters
...
public DockerCmdExecFactoryImpl withClientRequestFilters(ClientRequestFilter[] clientResponseFilters) {
checkNotNull(dockerClientConfig, "config was not specified");
this.clientRequestFilters = clientResponseFilters;
return this;
}

@OverRide
public void init() {
...
if (clientRequestFilters != null) {
for (ClientRequestFilter filter : clientRequestFilters) {
clientConfig.register(filter);
}
}
...
}

I then created my custom client request filter, like this:

public class MyCustomClientRequestFilter implements ClientRequestFilter{

private String user;
private String pass;
private int connectTimeout;

public MyCustomClientRequestFilter(int connectTimeout, String nginxUser, String nginxPass) {
    this.user = nginxUser;
    this.pass = nginxPass;
    this.connectTimeout = connectTimeout;
}

private String getBasicAuthentication() {
    String token = this.user + ":" + this.pass;
    try {
        return "BASIC " + DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException ex) {
        throw new IllegalStateException("Cannot encode with UTF-8", ex);
    }
}

@Override
public void filter(ClientRequestContext requestContext) throws IOException {
    requestContext.setProperty(ClientProperties.CONNECT_TIMEOUT, connectTimeout);
    requestContext.setProperty(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
    requestContext.getHeaders().add("Authorization", getBasicAuthentication());
}

}

And this is how I create my DockerClient instance:

public static DockerClient getDockerClient(String dockerRemoteApiUrl, String nginxUser, String nginxPass, String registryUser, String registryPass, String registryMail, String registryUrl){
DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder()
.withUri(dockerRemoteApiUrl)
.withUsername(registryUser)
.withPassword(registryPass)
.withEmail(registryMail)
.withServerAddress(registryUrl)
.build();

ClientRequestFilter[] filters = new ClientRequestFilter[]{
        new MyCustomClientRequestFilter(200, nginxUser, nginxPass),
};

DockerCmdExecFactoryImpl dockerCmdExecFactory = new DockerCmdExecFactoryImpl()
    .withDockerClientConfig(config)
    .withClientRequestFilters(filters);

return DockerClientBuilder.getInstance(config).withDockerCmdExecFactory(dockerCmdExecFactory).build();

}

I am not quite satisfied with the way I created the DockerClient instance.
I would think that having the request filters on the DockerClientConfig would be easier.

Eventually, your readTimeout, maxTotalConnection and maxPerRouteConnection could also be implemented within a ClientRequestFilter, although it might not be super obvious for integrators.

If this is okay for you, I would really love for this to become mainstream in the docker-java project :-)

Small detail though: connectTimeout is a quite common parameter for any connectivity implementation.
This specific one would be better off as standard in your implementation I think.

Again, thanks for your time and support.

Have a good day,

Eric Fjøsne

On 22 May 2015, at 23:53, marcuslinke [email protected] wrote:

@ericfjosne https://github.com/ericfjosne I've pushed a branch 'refact-config' (#226 #226) where I've factored out all JAXRS/ApacheConnector implementation specific parameters from DockerClientConfig. These and any additional ClientResponseFilters can be configured then via DockerCmdExecFactoryImpl directly.

Please take a look at it to see if you could implement your use case this way. Any comments are really welcome. Thanks!


Reply to this email directly or view it on GitHub #222 (comment).

@ericfjosne
Copy link
Copy Markdown
Author

Good morning again,

FYI, I pushed your refactored “refact-config” branch with my changes to my repository, with the same branch name.
https://github.com/ericfjosne/docker-java/tree/refact-config https://github.com/ericfjosne/docker-java/tree/refact-config

Have a good day !

Eric Fjøsne

On 09 Jul 2015, at 09:23, Eric Fjøsne [email protected] wrote:

Good morning Marcus,

Sorry for the long delay. I only had the chance to take a look at your suggestions tonight.
Thanks for your support on this matter, and the suggested implementation.

For the reminder, my fork added the 3 following features to your project:

Basic HTTP authentication on the docker API
Connect timeout parametrized configuration
Buffered request, which allow the HTTP request to be “replayed" if needed.

The ClientResponseFilters only applies after the communication is performed, while I needed something to adapt it beforehand.
My use case requires not a ClientResponseFilter but a ClientRequestFilter instead.

I tweaked your branch code (refact-config) a bit and managed to get it all working for me. Here is what I changed:

In your DockerCmdExecFactoryImpl, i changed the following:

private ClientRequestFilter[] clientRequestFilters; // instead of Class<? extends ClientResponseFilter>[] clientResponseFilters
...
public DockerCmdExecFactoryImpl withClientRequestFilters(ClientRequestFilter[] clientResponseFilters) {
checkNotNull(dockerClientConfig, "config was not specified");
this.clientRequestFilters = clientResponseFilters;
return this;
}

@OverRide
public void init() {
...
if (clientRequestFilters != null) {
for (ClientRequestFilter filter : clientRequestFilters) {
clientConfig.register(filter);
}
}
...
}

I then created my custom client request filter, like this:

public class MyCustomClientRequestFilter implements ClientRequestFilter{

private String user;
private String pass;
private int connectTimeout;

public MyCustomClientRequestFilter(int connectTimeout, String nginxUser, String nginxPass) {
this.user = nginxUser;
this.pass = nginxPass;
this.connectTimeout = connectTimeout;
}

private String getBasicAuthentication() {
String token = this.user + ":" + this.pass;
try {
return "BASIC " + DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new IllegalStateException("Cannot encode with UTF-8", ex);
}
}

@OverRide
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.setProperty(ClientProperties.CONNECT_TIMEOUT, connectTimeout);
requestContext.setProperty(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
requestContext.getHeaders().add("Authorization", getBasicAuthentication());
}
}

And this is how I create my DockerClient instance:

public static DockerClient getDockerClient(String dockerRemoteApiUrl, String nginxUser, String nginxPass, String registryUser, String registryPass, String registryMail, String registryUrl){
DockerClientConfig config = DockerClientConfig.createDefaultConfigBuilder()
.withUri(dockerRemoteApiUrl)
.withUsername(registryUser)
.withPassword(registryPass)
.withEmail(registryMail)
.withServerAddress(registryUrl)
.build();

ClientRequestFilter[] filters = new ClientRequestFilter[]{
new MyCustomClientRequestFilter(200, nginxUser, nginxPass),
};

DockerCmdExecFactoryImpl dockerCmdExecFactory = new DockerCmdExecFactoryImpl()
.withDockerClientConfig(config)
.withClientRequestFilters(filters);

return DockerClientBuilder.getInstance(config).withDockerCmdExecFactory(dockerCmdExecFactory).build();
}

I am not quite satisfied with the way I created the DockerClient instance.
I would think that having the request filters on the DockerClientConfig would be easier.

Eventually, your readTimeout, maxTotalConnection and maxPerRouteConnection could also be implemented within a ClientRequestFilter, although it might not be super obvious for integrators.

If this is okay for you, I would really love for this to become mainstream in the docker-java project :-)

Small detail though: connectTimeout is a quite common parameter for any connectivity implementation.
This specific one would be better off as standard in your implementation I think.

Again, thanks for your time and support.

Have a good day,

Eric Fjøsne

On 22 May 2015, at 23:53, marcuslinke <[email protected] mailto:[email protected]> wrote:

@ericfjosne https://github.com/ericfjosne I've pushed a branch 'refact-config' (#226 #226) where I've factored out all JAXRS/ApacheConnector implementation specific parameters from DockerClientConfig. These and any additional ClientResponseFilters can be configured then via DockerCmdExecFactoryImpl directly.

Please take a look at it to see if you could implement your use case this way. Any comments are really welcome. Thanks!


Reply to this email directly or view it on GitHub #222 (comment).

@marcuslinke
Copy link
Copy Markdown
Contributor

Hi Eric,

would it be possible to you to pull the latest changes from master into your branch and/or create a fresh PR?

Cheers

@marcuslinke
Copy link
Copy Markdown
Contributor

@ericfjosne I've created a fresh PR #282 Please review if this works for your use cases. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants