mirror of https://github.com/shred/acme4j
Catch IOExceptions early
parent
25700d5c41
commit
96d46784c6
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -26,7 +25,6 @@ import java.util.Map;
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
import org.shredzone.acme4j.challenge.Challenge;
|
||||||
import org.shredzone.acme4j.connector.Connection;
|
import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||||
import org.shredzone.acme4j.util.ClaimBuilder;
|
import org.shredzone.acme4j.util.ClaimBuilder;
|
||||||
|
@ -194,8 +192,6 @@ public class Authorization extends AcmeResource {
|
||||||
retryAfter);
|
retryAfter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,8 +209,6 @@ public class Authorization extends AcmeResource {
|
||||||
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
|
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
|
||||||
conn.throwAcmeException();
|
conn.throwAcmeException();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
@ -25,7 +24,6 @@ import java.util.List;
|
||||||
import org.shredzone.acme4j.connector.Connection;
|
import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.connector.Resource;
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||||
import org.shredzone.acme4j.util.ClaimBuilder;
|
import org.shredzone.acme4j.util.ClaimBuilder;
|
||||||
|
@ -106,8 +104,6 @@ public class Certificate extends AcmeResource {
|
||||||
|
|
||||||
chainCertUri = conn.getLink("up");
|
chainCertUri = conn.getLink("up");
|
||||||
cert = conn.readCertificate();
|
cert = conn.readCertificate();
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cert;
|
return cert;
|
||||||
|
@ -146,8 +142,6 @@ public class Certificate extends AcmeResource {
|
||||||
|
|
||||||
certChain.add(conn.readCertificate());
|
certChain.add(conn.readCertificate());
|
||||||
link = conn.getLink("up");
|
link = conn.getLink("up");
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
|
@ -200,8 +194,6 @@ public class Certificate extends AcmeResource {
|
||||||
}
|
}
|
||||||
} catch (CertificateEncodingException ex) {
|
} catch (CertificateEncodingException ex) {
|
||||||
throw new AcmeProtocolException("Invalid certificate", ex);
|
throw new AcmeProtocolException("Invalid certificate", ex);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
@ -35,7 +34,6 @@ import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.connector.Resource;
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
import org.shredzone.acme4j.connector.ResourceIterator;
|
import org.shredzone.acme4j.connector.ResourceIterator;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||||
import org.shredzone.acme4j.util.ClaimBuilder;
|
import org.shredzone.acme4j.util.ClaimBuilder;
|
||||||
|
@ -167,8 +165,6 @@ public class Registration extends AcmeResource {
|
||||||
|
|
||||||
Map<String, Object> json = conn.readJsonResponse();
|
Map<String, Object> json = conn.readJsonResponse();
|
||||||
unmarshal(json, conn);
|
unmarshal(json, conn);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +200,6 @@ public class Registration extends AcmeResource {
|
||||||
Authorization auth = new Authorization(getSession(), conn.getLocation());
|
Authorization auth = new Authorization(getSession(), conn.getLocation());
|
||||||
auth.unmarshalAuthorization(json);
|
auth.unmarshalAuthorization(json);
|
||||||
return auth;
|
return auth;
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,8 +262,6 @@ public class Registration extends AcmeResource {
|
||||||
URI chainCertUri = conn.getLink("up");
|
URI chainCertUri = conn.getLink("up");
|
||||||
|
|
||||||
return new Certificate(getSession(), conn.getLocation(), chainCertUri, cert);
|
return new Certificate(getSession(), conn.getLocation(), chainCertUri, cert);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,8 +313,6 @@ public class Registration extends AcmeResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
getSession().setKeyPair(newKeyPair);
|
getSession().setKeyPair(newKeyPair);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
} catch (JoseException ex) {
|
} catch (JoseException ex) {
|
||||||
throw new AcmeProtocolException("Cannot sign key-change", ex);
|
throw new AcmeProtocolException("Cannot sign key-change", ex);
|
||||||
}
|
}
|
||||||
|
@ -345,8 +335,6 @@ public class Registration extends AcmeResource {
|
||||||
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
|
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
|
||||||
conn.throwAcmeException();
|
conn.throwAcmeException();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,8 +505,6 @@ public class Registration extends AcmeResource {
|
||||||
|
|
||||||
Map<String, Object> json = conn.readJsonResponse();
|
Map<String, Object> json = conn.readJsonResponse();
|
||||||
unmarshal(json, conn);
|
unmarshal(json, conn);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j;
|
package org.shredzone.acme4j;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -23,7 +22,6 @@ import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.connector.Resource;
|
import org.shredzone.acme4j.connector.Resource;
|
||||||
import org.shredzone.acme4j.exception.AcmeConflictException;
|
import org.shredzone.acme4j.exception.AcmeConflictException;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
import org.shredzone.acme4j.util.ClaimBuilder;
|
import org.shredzone.acme4j.util.ClaimBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -92,8 +90,6 @@ public class RegistrationBuilder {
|
||||||
URI tos = conn.getLink("terms-of-service");
|
URI tos = conn.getLink("terms-of-service");
|
||||||
|
|
||||||
return new Registration(session, location, tos);
|
return new Registration(session, location, tos);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.Status;
|
import org.shredzone.acme4j.Status;
|
||||||
import org.shredzone.acme4j.connector.Connection;
|
import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
|
||||||
import org.shredzone.acme4j.util.ClaimBuilder;
|
import org.shredzone.acme4j.util.ClaimBuilder;
|
||||||
|
@ -88,8 +87,6 @@ public class Challenge extends AcmeResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (T) session.createChallenge(json);
|
return (T) session.createChallenge(json);
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,8 +217,6 @@ public class Challenge extends AcmeResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
unmarshall(conn.readJsonResponse());
|
unmarshall(conn.readJsonResponse());
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +247,6 @@ public class Challenge extends AcmeResource {
|
||||||
retryAfter);
|
retryAfter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.connector;
|
package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -39,7 +38,7 @@ public interface Connection extends AutoCloseable {
|
||||||
* {@link Session} instance to be used for tracking
|
* {@link Session} instance to be used for tracking
|
||||||
* @return HTTP response code
|
* @return HTTP response code
|
||||||
*/
|
*/
|
||||||
int sendRequest(URI uri, Session session) throws IOException;
|
int sendRequest(URI uri, Session session) throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a signed POST request.
|
* Sends a signed POST request.
|
||||||
|
@ -52,21 +51,21 @@ public interface Connection extends AutoCloseable {
|
||||||
* {@link Session} instance to be used for signing and tracking
|
* {@link Session} instance to be used for signing and tracking
|
||||||
* @return HTTP response code
|
* @return HTTP response code
|
||||||
*/
|
*/
|
||||||
int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws IOException;
|
int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a server response as JSON data.
|
* Reads a server response as JSON data.
|
||||||
*
|
*
|
||||||
* @return Map containing the parsed JSON data
|
* @return Map containing the parsed JSON data
|
||||||
*/
|
*/
|
||||||
Map<String, Object> readJsonResponse() throws IOException;
|
Map<String, Object> readJsonResponse() throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a certificate.
|
* Reads a certificate.
|
||||||
*
|
*
|
||||||
* @return {@link X509Certificate} that was read.
|
* @return {@link X509Certificate} that was read.
|
||||||
*/
|
*/
|
||||||
X509Certificate readCertificate() throws IOException;
|
X509Certificate readCertificate() throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a {@link Session} by evaluating the HTTP response header.
|
* Updates a {@link Session} by evaluating the HTTP response header.
|
||||||
|
@ -120,7 +119,7 @@ public interface Connection extends AutoCloseable {
|
||||||
* {@link AcmeServerException} will be thrown. Otherwise a generic
|
* {@link AcmeServerException} will be thrown. Otherwise a generic
|
||||||
* {@link AcmeException} is thrown.
|
* {@link AcmeException} is thrown.
|
||||||
*/
|
*/
|
||||||
void throwAcmeException() throws AcmeException, IOException;
|
void throwAcmeException() throws AcmeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the {@link Connection}, releasing all resources.
|
* Closes the {@link Connection}, releasing all resources.
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.exception.AcmeAgreementRequiredException;
|
import org.shredzone.acme4j.exception.AcmeAgreementRequiredException;
|
||||||
import org.shredzone.acme4j.exception.AcmeConflictException;
|
import org.shredzone.acme4j.exception.AcmeConflictException;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.exception.AcmeRateLimitExceededException;
|
import org.shredzone.acme4j.exception.AcmeRateLimitExceededException;
|
||||||
import org.shredzone.acme4j.exception.AcmeServerException;
|
import org.shredzone.acme4j.exception.AcmeServerException;
|
||||||
|
@ -78,7 +79,7 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sendRequest(URI uri, Session session) throws IOException {
|
public int sendRequest(URI uri, Session session) throws AcmeException {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
throw new NullPointerException("uri must not be null");
|
throw new NullPointerException("uri must not be null");
|
||||||
}
|
}
|
||||||
|
@ -89,21 +90,25 @@ public class DefaultConnection implements Connection {
|
||||||
|
|
||||||
LOG.debug("GET {}", uri);
|
LOG.debug("GET {}", uri);
|
||||||
|
|
||||||
conn = httpConnector.openConnection(uri);
|
try {
|
||||||
conn.setRequestMethod("GET");
|
conn = httpConnector.openConnection(uri);
|
||||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
conn.setRequestMethod("GET");
|
||||||
conn.setRequestProperty("Accept-Language", session.getLocale().toLanguageTag());
|
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||||
conn.setDoOutput(false);
|
conn.setRequestProperty("Accept-Language", session.getLocale().toLanguageTag());
|
||||||
|
conn.setDoOutput(false);
|
||||||
|
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
logHeaders();
|
logHeaders();
|
||||||
|
|
||||||
return conn.getResponseCode();
|
return conn.getResponseCode();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AcmeNetworkException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws IOException {
|
public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) throws AcmeException {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
throw new NullPointerException("uri must not be null");
|
throw new NullPointerException("uri must not be null");
|
||||||
}
|
}
|
||||||
|
@ -165,13 +170,15 @@ public class DefaultConnection implements Connection {
|
||||||
updateSession(session);
|
updateSession(session);
|
||||||
|
|
||||||
return conn.getResponseCode();
|
return conn.getResponseCode();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AcmeNetworkException(ex);
|
||||||
} catch (JoseException ex) {
|
} catch (JoseException ex) {
|
||||||
throw new AcmeProtocolException("Failed to generate a JSON request", ex);
|
throw new AcmeProtocolException("Failed to generate a JSON request", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> readJsonResponse() throws IOException {
|
public Map<String, Object> readJsonResponse() throws AcmeException {
|
||||||
assertConnectionIsOpen();
|
assertConnectionIsOpen();
|
||||||
|
|
||||||
String contentType = conn.getHeaderField("Content-Type");
|
String contentType = conn.getHeaderField("Content-Type");
|
||||||
|
@ -190,6 +197,8 @@ public class DefaultConnection implements Connection {
|
||||||
result = JsonUtil.parseJson(response);
|
result = JsonUtil.parseJson(response);
|
||||||
LOG.debug("Result JSON: {}", response);
|
LOG.debug("Result JSON: {}", response);
|
||||||
}
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AcmeNetworkException(ex);
|
||||||
} catch (JoseException ex) {
|
} catch (JoseException ex) {
|
||||||
throw new AcmeProtocolException("Failed to parse response: " + response, ex);
|
throw new AcmeProtocolException("Failed to parse response: " + response, ex);
|
||||||
}
|
}
|
||||||
|
@ -213,7 +222,7 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public X509Certificate readCertificate() throws IOException {
|
public X509Certificate readCertificate() throws AcmeException {
|
||||||
assertConnectionIsOpen();
|
assertConnectionIsOpen();
|
||||||
|
|
||||||
String contentType = conn.getHeaderField("Content-Type");
|
String contentType = conn.getHeaderField("Content-Type");
|
||||||
|
@ -224,6 +233,8 @@ public class DefaultConnection implements Connection {
|
||||||
try (InputStream in = conn.getInputStream()) {
|
try (InputStream in = conn.getInputStream()) {
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
return (X509Certificate) cf.generateCertificate(in);
|
return (X509Certificate) cf.generateCertificate(in);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AcmeNetworkException(ex);
|
||||||
} catch (CertificateException ex) {
|
} catch (CertificateException ex) {
|
||||||
throw new AcmeProtocolException("Failed to read certificate", ex);
|
throw new AcmeProtocolException("Failed to read certificate", ex);
|
||||||
}
|
}
|
||||||
|
@ -323,49 +334,49 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void throwAcmeException() throws AcmeException, IOException {
|
public void throwAcmeException() throws AcmeException {
|
||||||
assertConnectionIsOpen();
|
assertConnectionIsOpen();
|
||||||
|
|
||||||
if ("application/problem+json".equals(conn.getHeaderField("Content-Type"))) {
|
if (!"application/problem+json".equals(conn.getHeaderField("Content-Type"))) {
|
||||||
Map<String, Object> map = readJsonResponse();
|
throw new AcmeException("HTTP " + getResponseCode() + ": " + getResponseMessage());
|
||||||
String type = (String) map.get("type");
|
}
|
||||||
String detail = (String) map.get("detail");
|
|
||||||
|
|
||||||
if (detail == null) {
|
Map<String, Object> map = readJsonResponse();
|
||||||
detail = "general problem";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) {
|
String type = (String) map.get("type");
|
||||||
throw new AcmeConflictException(detail, getLocation());
|
String detail = (String) map.get("detail");
|
||||||
}
|
|
||||||
|
|
||||||
if (type == null) {
|
if (detail == null) {
|
||||||
throw new AcmeException(detail);
|
detail = "general problem";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
if (getResponseCode() == HttpURLConnection.HTTP_CONFLICT) {
|
||||||
case ACME_ERROR_PREFIX + "unauthorized":
|
throw new AcmeConflictException(detail, getLocation());
|
||||||
case ACME_ERROR_PREFIX_DEPRECATED + "unauthorized":
|
}
|
||||||
throw new AcmeUnauthorizedException(type, detail);
|
|
||||||
|
|
||||||
case ACME_ERROR_PREFIX + "agreementRequired":
|
if (type == null) {
|
||||||
case ACME_ERROR_PREFIX_DEPRECATED + "agreementRequired":
|
throw new AcmeException(detail);
|
||||||
String instance = (String) map.get("instance");
|
}
|
||||||
throw new AcmeAgreementRequiredException(
|
|
||||||
type, detail, getLink("terms-of-service"),
|
|
||||||
(instance != null ? resolveRelative(instance) : null));
|
|
||||||
|
|
||||||
case ACME_ERROR_PREFIX + "rateLimited":
|
switch (type) {
|
||||||
case ACME_ERROR_PREFIX_DEPRECATED + "rateLimited":
|
case ACME_ERROR_PREFIX + "unauthorized":
|
||||||
throw new AcmeRateLimitExceededException(
|
case ACME_ERROR_PREFIX_DEPRECATED + "unauthorized":
|
||||||
type, detail, getRetryAfterHeader(), getLinks("rate-limit"));
|
throw new AcmeUnauthorizedException(type, detail);
|
||||||
|
|
||||||
default:
|
case ACME_ERROR_PREFIX + "agreementRequired":
|
||||||
throw new AcmeServerException(type, detail);
|
case ACME_ERROR_PREFIX_DEPRECATED + "agreementRequired":
|
||||||
}
|
String instance = (String) map.get("instance");
|
||||||
} else {
|
throw new AcmeAgreementRequiredException(
|
||||||
throw new AcmeException("HTTP " + conn.getResponseCode() + ": "
|
type, detail, getLink("terms-of-service"),
|
||||||
+ conn.getResponseMessage());
|
instance != null ? resolveRelative(instance) : null);
|
||||||
|
|
||||||
|
case ACME_ERROR_PREFIX + "rateLimited":
|
||||||
|
case ACME_ERROR_PREFIX_DEPRECATED + "rateLimited":
|
||||||
|
throw new AcmeRateLimitExceededException(
|
||||||
|
type, detail, getRetryAfterHeader(), getLinks("rate-limit"));
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new AcmeServerException(type, detail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,6 +403,28 @@ public class DefaultConnection implements Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last response code.
|
||||||
|
*/
|
||||||
|
private int getResponseCode() throws AcmeException {
|
||||||
|
try {
|
||||||
|
return conn.getResponseCode();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AcmeNetworkException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last response message.
|
||||||
|
*/
|
||||||
|
private String getResponseMessage() throws AcmeException {
|
||||||
|
try {
|
||||||
|
return conn.getResponseMessage();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new AcmeNetworkException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log all HTTP headers in debug mode.
|
* Log all HTTP headers in debug mode.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.connector;
|
package org.shredzone.acme4j.connector;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
@ -27,7 +26,6 @@ import java.util.NoSuchElementException;
|
||||||
import org.shredzone.acme4j.AcmeResource;
|
import org.shredzone.acme4j.AcmeResource;
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,7 +142,6 @@ public abstract class ResourceIterator<T extends AcmeResource> implements Iterat
|
||||||
* Reads the next batch of URIs from the server, and fills the queue with the URIs. If
|
* Reads the next batch of URIs from the server, and fills the queue with the URIs. If
|
||||||
* there is a "next" header, it is used for the next batch of URIs.
|
* there is a "next" header, it is used for the next batch of URIs.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void readAndQueue() throws AcmeException {
|
private void readAndQueue() throws AcmeException {
|
||||||
try (Connection conn = session.provider().connect()) {
|
try (Connection conn = session.provider().connect()) {
|
||||||
int rc = conn.sendRequest(nextUri, session);
|
int rc = conn.sendRequest(nextUri, session);
|
||||||
|
@ -153,22 +150,33 @@ public abstract class ResourceIterator<T extends AcmeResource> implements Iterat
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> json = conn.readJsonResponse();
|
Map<String, Object> json = conn.readJsonResponse();
|
||||||
try {
|
fillUriList(json);
|
||||||
Collection<String> array = (Collection<String>) json.get(field);
|
|
||||||
if (array != null) {
|
|
||||||
for (String uri : array) {
|
|
||||||
uriList.add(new URI(uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassCastException ex) {
|
|
||||||
throw new AcmeProtocolException("Expected an array");
|
|
||||||
} catch (URISyntaxException ex) {
|
|
||||||
throw new AcmeProtocolException("Invalid URI", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
nextUri = conn.getLink("next");
|
nextUri = conn.getLink("next");
|
||||||
} catch (IOException ex) {
|
}
|
||||||
throw new AcmeNetworkException(ex);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills the uri list with the URIs found in the desired field.
|
||||||
|
*
|
||||||
|
* @param json
|
||||||
|
* JSON map to read from
|
||||||
|
*/
|
||||||
|
private void fillUriList(Map<String, Object> json) {
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Collection<String> array = (Collection<String>) json.get(field);
|
||||||
|
if (array == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String uri : array) {
|
||||||
|
uriList.add(new URI(uri));
|
||||||
|
}
|
||||||
|
} catch (ClassCastException ex) {
|
||||||
|
throw new AcmeProtocolException("Expected an array", ex);
|
||||||
|
} catch (URISyntaxException ex) {
|
||||||
|
throw new AcmeProtocolException("Invalid URI", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.provider;
|
package org.shredzone.acme4j.provider;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -28,7 +27,6 @@ import org.shredzone.acme4j.connector.Connection;
|
||||||
import org.shredzone.acme4j.connector.DefaultConnection;
|
import org.shredzone.acme4j.connector.DefaultConnection;
|
||||||
import org.shredzone.acme4j.connector.HttpConnector;
|
import org.shredzone.acme4j.connector.HttpConnector;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract implementation of {@link AcmeProvider}. It consists of a challenge
|
* Abstract implementation of {@link AcmeProvider}. It consists of a challenge
|
||||||
|
@ -56,8 +54,6 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
|
||||||
conn.updateSession(session);
|
conn.updateSession(session);
|
||||||
|
|
||||||
return conn.readJsonResponse();
|
return conn.readJsonResponse();
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new AcmeNetworkException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.junit.Test;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.shredzone.acme4j.Session;
|
import org.shredzone.acme4j.Session;
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
import org.shredzone.acme4j.exception.AcmeException;
|
||||||
|
import org.shredzone.acme4j.exception.AcmeNetworkException;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
import org.shredzone.acme4j.exception.AcmeServerException;
|
import org.shredzone.acme4j.exception.AcmeServerException;
|
||||||
import org.shredzone.acme4j.util.ClaimBuilder;
|
import org.shredzone.acme4j.util.ClaimBuilder;
|
||||||
|
@ -358,7 +359,7 @@ public class DefaultConnectionTest {
|
||||||
assertThat(ex.getType(), is("urn:zombie:error:apocalypse"));
|
assertThat(ex.getType(), is("urn:zombie:error:apocalypse"));
|
||||||
assertThat(ex.getMessage(), is("Zombie apocalypse in progress"));
|
assertThat(ex.getMessage(), is("Zombie apocalypse in progress"));
|
||||||
assertThat(ex.getAcmeErrorType(), is(nullValue()));
|
assertThat(ex.getAcmeErrorType(), is(nullValue()));
|
||||||
} catch (AcmeException | IOException ex) {
|
} catch (AcmeException ex) {
|
||||||
fail("Expected an AcmeServerException");
|
fail("Expected an AcmeServerException");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,10 +387,10 @@ public class DefaultConnectionTest {
|
||||||
conn.conn = mockUrlConnection;
|
conn.conn = mockUrlConnection;
|
||||||
conn.throwAcmeException();
|
conn.throwAcmeException();
|
||||||
fail("Expected to fail");
|
fail("Expected to fail");
|
||||||
|
} catch (AcmeNetworkException ex) {
|
||||||
|
fail("Did not expect an AcmeNetworkException");
|
||||||
} catch (AcmeException ex) {
|
} catch (AcmeException ex) {
|
||||||
assertThat(ex.getMessage(), not(isEmptyOrNullString()));
|
assertThat(ex.getMessage(), not(isEmptyOrNullString()));
|
||||||
} catch (IOException ex) {
|
|
||||||
fail("Expected an AcmeException");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockUrlConnection).getHeaderField("Content-Type");
|
verify(mockUrlConnection).getHeaderField("Content-Type");
|
||||||
|
|
Loading…
Reference in New Issue