Add support for Proxy connections

pull/61/head
Richard Körber 2018-03-06 22:11:05 +01:00
parent b4374dbf6d
commit 49677d8dbc
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
8 changed files with 52 additions and 11 deletions

View File

@ -13,6 +13,7 @@
*/ */
package org.shredzone.acme4j; package org.shredzone.acme4j;
import java.net.Proxy;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.security.KeyPair; import java.security.KeyPair;
@ -42,6 +43,7 @@ public class Session {
private String nonce; private String nonce;
private Locale locale = Locale.getDefault(); private Locale locale = Locale.getDefault();
private Proxy proxy = Proxy.NO_PROXY;
protected Instant directoryCacheExpiry; protected Instant directoryCacheExpiry;
/** /**
@ -128,6 +130,21 @@ public class Session {
this.locale = locale; this.locale = locale;
} }
/**
* Gets the {@link Proxy} to be used for connections.
*/
public Proxy getProxy() {
return proxy;
}
/**
* Sets a {@link Proxy} that is to be used for all connections. If {@code null},
* {@link Proxy#NO_PROXY} is used, which is also the default.
*/
public void setProxy(Proxy proxy) {
this.proxy = proxy != null ? proxy : Proxy.NO_PROXY;
}
/** /**
* Returns the {@link AcmeProvider} that is used for this session. * Returns the {@link AcmeProvider} that is used for this session.
* *

View File

@ -101,7 +101,7 @@ public class DefaultConnection implements Connection {
URL newNonceUrl = session.resourceUrl(Resource.NEW_NONCE); URL newNonceUrl = session.resourceUrl(Resource.NEW_NONCE);
conn = httpConnector.openConnection(newNonceUrl); conn = httpConnector.openConnection(newNonceUrl, session.getProxy());
conn.setRequestMethod("HEAD"); conn.setRequestMethod("HEAD");
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag()); conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
conn.connect(); conn.connect();
@ -132,7 +132,7 @@ public class DefaultConnection implements Connection {
LOG.debug("GET {}", url); LOG.debug("GET {}", url);
try { try {
conn = httpConnector.openConnection(url); conn = httpConnector.openConnection(url, session.getProxy());
conn.setRequestMethod("GET"); conn.setRequestMethod("GET");
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET); conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag()); conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
@ -311,7 +311,7 @@ public class DefaultConnection implements Connection {
resetNonce(session); resetNonce(session);
} }
conn = httpConnector.openConnection(url); conn = httpConnector.openConnection(url, session.getProxy());
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
conn.setRequestProperty(ACCEPT_HEADER, "application/json"); conn.setRequestProperty(ACCEPT_HEADER, "application/json");
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET); conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);

View File

@ -16,6 +16,7 @@ package org.shredzone.acme4j.connector;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL; import java.net.URL;
import java.util.Properties; import java.util.Properties;
@ -63,10 +64,12 @@ public class HttpConnector {
* *
* @param url * @param url
* {@link URL} to connect to * {@link URL} to connect to
* @param proxy
* {@link Proxy} to be used
* @return {@link HttpURLConnection} connected to the {@link URL} * @return {@link HttpURLConnection} connected to the {@link URL}
*/ */
public HttpURLConnection openConnection(URL url) throws IOException { public HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
configure(conn); configure(conn);
return conn; return conn;
} }

View File

@ -16,6 +16,7 @@ package org.shredzone.acme4j.provider.pebble;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL; import java.net.URL;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStore; import java.security.KeyStore;
@ -39,8 +40,8 @@ public class PebbleHttpConnector extends HttpConnector {
private static SSLSocketFactory sslSocketFactory; private static SSLSocketFactory sslSocketFactory;
@Override @Override
public HttpURLConnection openConnection(URL url) throws IOException { public HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
HttpURLConnection conn = super.openConnection(url); HttpURLConnection conn = super.openConnection(url, proxy);
if (conn instanceof HttpsURLConnection) { if (conn instanceof HttpsURLConnection) {
((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory()); ((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory());
} }

View File

@ -19,6 +19,9 @@ import static org.mockito.Mockito.*;
import static org.shredzone.acme4j.toolbox.TestUtils.*; import static org.shredzone.acme4j.toolbox.TestUtils.*;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.security.KeyPair; import java.security.KeyPair;
@ -79,6 +82,13 @@ public class SessionTest {
session.setNonce(DUMMY_NONCE); session.setNonce(DUMMY_NONCE);
assertThat(session.getNonce(), is(equalTo(DUMMY_NONCE))); assertThat(session.getNonce(), is(equalTo(DUMMY_NONCE)));
assertThat(session.getProxy(), is(Proxy.NO_PROXY));
Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress("10.0.0.1", 8080));
session.setProxy(proxy);
assertThat(session.getProxy(), is(proxy));
session.setProxy(null);
assertThat(session.getProxy(), is(Proxy.NO_PROXY));
assertThat(session.getServerUri(), is(serverUri)); assertThat(session.getServerUri(), is(serverUri));
} }

View File

@ -24,6 +24,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.security.KeyPair; import java.security.KeyPair;
@ -78,7 +79,7 @@ public class DefaultConnectionTest {
mockUrlConnection = mock(HttpURLConnection.class); mockUrlConnection = mock(HttpURLConnection.class);
mockHttpConnection = mock(HttpConnector.class); mockHttpConnection = mock(HttpConnector.class);
when(mockHttpConnection.openConnection(requestUrl)).thenReturn(mockUrlConnection); when(mockHttpConnection.openConnection(requestUrl, Proxy.NO_PROXY)).thenReturn(mockUrlConnection);
final AcmeProvider mockProvider = mock(AcmeProvider.class); final AcmeProvider mockProvider = mock(AcmeProvider.class);
when(mockProvider.directory( when(mockProvider.directory(
@ -158,7 +159,7 @@ public class DefaultConnectionTest {
*/ */
@Test @Test
public void testResetNonce() throws AcmeException, IOException { public void testResetNonce() throws AcmeException, IOException {
when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce"))) when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce"), Proxy.NO_PROXY))
.thenReturn(mockUrlConnection); .thenReturn(mockUrlConnection);
when(mockUrlConnection.getResponseCode()) when(mockUrlConnection.getResponseCode())
.thenReturn(HttpURLConnection.HTTP_NO_CONTENT); .thenReturn(HttpURLConnection.HTTP_NO_CONTENT);
@ -813,7 +814,7 @@ public class DefaultConnectionTest {
*/ */
@Test(expected = AcmeException.class) @Test(expected = AcmeException.class)
public void testSendSignedRequestNoNonce() throws Exception { public void testSendSignedRequestNoNonce() throws Exception {
when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce"))) when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce"), Proxy.NO_PROXY))
.thenReturn(mockUrlConnection); .thenReturn(mockUrlConnection);
when(mockUrlConnection.getResponseCode()) when(mockUrlConnection.getResponseCode())
.thenReturn(HttpURLConnection.HTTP_NOT_FOUND); .thenReturn(HttpURLConnection.HTTP_NOT_FOUND);

View File

@ -20,6 +20,7 @@ import static org.mockito.Mockito.*;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
@ -59,7 +60,7 @@ public class HttpConnectorTest {
@Category(HttpURLConnection.class) @Category(HttpURLConnection.class)
public void testOpenConnection() throws IOException { public void testOpenConnection() throws IOException {
HttpConnector connector = new HttpConnector(); HttpConnector connector = new HttpConnector();
HttpURLConnection conn = connector.openConnection(new URL("http://example.com")); HttpURLConnection conn = connector.openConnection(new URL("http://example.com"), Proxy.NO_PROXY);
assertThat(conn, not(nullValue())); assertThat(conn, not(nullValue()));
conn.connect(); conn.connect();
assertThat(conn.getResponseCode(), is(HttpURLConnection.HTTP_OK)); assertThat(conn.getResponseCode(), is(HttpURLConnection.HTTP_OK));

View File

@ -34,3 +34,11 @@ URL website = meta.getWebsite();
`Session.setLocale()` allows to select a different locale. Errors will be returned in that language, if supported by the CA. `Session.setLocale()` allows to select a different locale. Errors will be returned in that language, if supported by the CA.
By default, the system's default locale is used. By default, the system's default locale is used.
## Proxy
_acme4j_ uses a standard `HttpURLConnection` for HTTP connections.
If a proxy must be used for internet connections, you can set a `Proxy` instance by invoking `Session.setProxy()`. An alternative is to use the system properties `http.proxyHost` and `http.proxyPort` to globally set a proxy for the Java process.
If the proxy needs authentication, you need to set a default `Authenticator`. Be careful: Most code snippets I have found in the internet will send out the proxy credentials to anyone who is asking. See [this blog article](http://rolandtapken.de/blog/2012-04/java-process-httpproxyuser-and-httpproxypassword) for a good way to implement a proxy `Authenticator`.