-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Retries registry call with HTTP if HTTPS fails. #407
Changes from all commits
03ea6b6
2a93350
107904a
a370494
764d91e
d2b78e6
23580e3
b9e7f7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,12 +26,15 @@ | |
import com.google.cloud.tools.jib.json.JsonTemplateMapper; | ||
import com.google.cloud.tools.jib.registry.json.ErrorEntryTemplate; | ||
import com.google.cloud.tools.jib.registry.json.ErrorResponseTemplate; | ||
import com.google.common.annotations.VisibleForTesting; | ||
import java.io.IOException; | ||
import java.net.MalformedURLException; | ||
import java.net.URL; | ||
import java.util.function.Function; | ||
import javax.annotation.Nullable; | ||
import javax.net.ssl.SSLPeerUnverifiedException; | ||
import org.apache.http.NoHttpResponseException; | ||
import org.apache.http.conn.HttpHostConnectException; | ||
|
||
/** | ||
* Makes requests to a registry endpoint. | ||
|
@@ -50,15 +53,29 @@ private static class RequestState { | |
|
||
/** | ||
* @param authorization authentication credentials | ||
* @param url the endpoint URL to call, or {@code null} to use default from {@code | ||
* registryEndpointProvider} | ||
* @param url the endpoint URL to call | ||
*/ | ||
private RequestState(@Nullable Authorization authorization, URL url) { | ||
this.authorization = authorization; | ||
this.url = url; | ||
} | ||
} | ||
|
||
/** | ||
* Converts the {@link URL}'s protocol to HTTP. | ||
* | ||
* @param url the URL to conver to HTTP | ||
* @return the URL with protocol set to HTTP | ||
*/ | ||
private static URL urlWithHttp(URL url) { | ||
GenericUrl httpUrl = new GenericUrl(url); | ||
httpUrl.setScheme("http"); | ||
return httpUrl.toURL(); | ||
} | ||
|
||
/** Makes a {@link Connection} to the specified {@link URL}. */ | ||
private final Function<URL, Connection> connectionFactory; | ||
|
||
private final RequestState initialRequestState; | ||
private final String userAgent; | ||
private final RegistryEndpointProvider<T> registryEndpointProvider; | ||
|
@@ -81,13 +98,32 @@ private RequestState(@Nullable Authorization authorization, URL url) { | |
@Nullable Authorization authorization, | ||
RegistryEndpointProperties registryEndpointProperties) | ||
throws MalformedURLException { | ||
this( | ||
userAgent, | ||
apiRouteBase, | ||
registryEndpointProvider, | ||
authorization, | ||
registryEndpointProperties, | ||
Connection::new); | ||
} | ||
|
||
@VisibleForTesting | ||
RegistryEndpointCaller( | ||
String userAgent, | ||
String apiRouteBase, | ||
RegistryEndpointProvider<T> registryEndpointProvider, | ||
@Nullable Authorization authorization, | ||
RegistryEndpointProperties registryEndpointProperties, | ||
Function<URL, Connection> connectionFactory) | ||
throws MalformedURLException { | ||
this.initialRequestState = | ||
new RequestState( | ||
authorization, | ||
registryEndpointProvider.getApiRoute(DEFAULT_PROTOCOL + "://" + apiRouteBase)); | ||
this.userAgent = userAgent; | ||
this.registryEndpointProvider = registryEndpointProvider; | ||
this.registryEndpointProperties = registryEndpointProperties; | ||
this.connectionFactory = connectionFactory; | ||
} | ||
|
||
/** | ||
|
@@ -102,10 +138,18 @@ T call() throws IOException, RegistryException { | |
return call(initialRequestState); | ||
} | ||
|
||
/** Calls the registry endpoint with a certain {@link RequestState}. */ | ||
/** | ||
* Calls the registry endpoint with a certain {@link RequestState}. | ||
* | ||
* @param requestState the state of the request - determines how to make the request and how to | ||
* process the response | ||
* @return an object representing the response, or {@code null} | ||
* @throws IOException for most I/O exceptions when making the request | ||
* @throws RegistryException for known exceptions when interacting with the registry | ||
*/ | ||
@Nullable | ||
private T call(RequestState requestState) throws IOException, RegistryException { | ||
try (Connection connection = new Connection(requestState.url)) { | ||
try (Connection connection = connectionFactory.apply(requestState.url)) { | ||
Request request = | ||
Request.builder() | ||
.setAuthorization(requestState.authorization) | ||
|
@@ -161,14 +205,16 @@ private T call(RequestState requestState) throws IOException, RegistryException | |
} | ||
} | ||
|
||
} catch (HttpHostConnectException | SSLPeerUnverifiedException ex) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about this, but is it possible users might not want this insecure fallback mechanism? What if they always want to use https or fail? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, yea it seems that we might want to have the user enable the fallback to HTTP with a configuration option, since Docker only seems to allow insecure registries with a flag. |
||
// Tries to call with HTTP protocol if HTTPS failed to connect. | ||
if ("https".equals(requestState.url.getProtocol())) { | ||
return call(new RequestState(requestState.authorization, urlWithHttp(requestState.url))); | ||
} | ||
|
||
throw ex; | ||
|
||
} catch (NoHttpResponseException ex) { | ||
throw new RegistryNoResponseException(ex); | ||
|
||
} catch (SSLPeerUnverifiedException ex) { | ||
// Fall-back to HTTP | ||
GenericUrl httpUrl = new GenericUrl(requestState.url); | ||
httpUrl.setScheme("http"); | ||
return call(new RequestState(requestState.authorization, httpUrl.toURL())); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should these be @link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you mean like
@throws IOException for most {@link IOException}s when making the request
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope. Please ignore. I shouldn't make review comments so early in the morning.