Retry on bad nonce error

pull/55/head
Richard Körber 2017-12-14 00:05:46 +01:00
parent 2b61478f13
commit 2ceffa42e3
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
23 changed files with 261 additions and 376 deletions

View File

@ -131,7 +131,6 @@ public class Account extends AcmeResource {
JSONBuilder claims = new JSONBuilder();
conn.sendSignedRequest(getLocation(), claims, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
unmarshal(conn.readJsonResponse());
}
@ -180,8 +179,7 @@ public class Account extends AcmeResource {
.put("type", "dns")
.put("value", toAce(domain));
conn.sendSignedRequest(newAuthzUrl, claims, getSession());
conn.accept(HttpURLConnection.HTTP_CREATED);
conn.sendSignedRequest(newAuthzUrl, claims, getSession(), HttpURLConnection.HTTP_CREATED);
JSON json = conn.readJsonResponse();
@ -231,7 +229,6 @@ public class Account extends AcmeResource {
outerClaim.put("payload", innerJws.getEncodedPayload());
conn.sendSignedRequest(keyChangeUrl, outerClaim, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
getSession().setKeyPair(newKeyPair);
} catch (JoseException ex) {
@ -252,7 +249,6 @@ public class Account extends AcmeResource {
claims.put(KEY_STATUS, "deactivated");
conn.sendSignedRequest(getLocation(), claims, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
unmarshal(conn.readJsonResponse());
}
@ -366,7 +362,6 @@ public class Account extends AcmeResource {
}
conn.sendSignedRequest(getLocation(), claims, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
JSON json = conn.readJsonResponse();
unmarshal(json);

View File

@ -177,8 +177,7 @@ public class AccountBuilder {
claims.put("only-return-existing", onlyExisting);
}
conn.sendSignedRequest(resourceUrl, claims, session, true);
int resp = conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED);
int resp = conn.sendSignedRequest(resourceUrl, claims, session, true, HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED);
URL location = conn.getLocation();

View File

@ -16,7 +16,6 @@ package org.shredzone.acme4j;
import static java.util.stream.Collectors.toList;
import static org.shredzone.acme4j.toolbox.AcmeUtils.parseTimestamp;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Instant;
import java.util.Collections;
@ -131,7 +130,6 @@ public class Authorization extends AcmeResource {
LOG.debug("update");
try (Connection conn = getSession().provider().connect()) {
conn.sendRequest(getLocation(), getSession());
conn.accept(HttpURLConnection.HTTP_OK);
unmarshalAuthorization(conn.readJsonResponse());
@ -149,7 +147,6 @@ public class Authorization extends AcmeResource {
claims.put("status", "deactivated");
conn.sendSignedRequest(getLocation(), claims, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
unmarshalAuthorization(conn.readJsonResponse());
}

View File

@ -17,7 +17,6 @@ import static java.util.Collections.unmodifiableList;
import java.io.IOException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.security.KeyPair;
@ -82,7 +81,6 @@ public class Certificate extends AcmeResource {
LOG.debug("download");
try (Connection conn = getSession().provider().connect()) {
conn.sendRequest(getLocation(), getSession());
conn.accept(HttpURLConnection.HTTP_OK);
alternates = new ArrayList<>(conn.getLinks("alternate"));
certChain = new ArrayList<>(conn.readCertificates());
}
@ -172,7 +170,6 @@ public class Certificate extends AcmeResource {
}
conn.sendSignedRequest(resUrl, claims, getSession(), true);
conn.accept(HttpURLConnection.HTTP_OK);
} catch (CertificateEncodingException ex) {
throw new AcmeProtocolException("Invalid certificate", ex);
}
@ -211,7 +208,6 @@ public class Certificate extends AcmeResource {
}
conn.sendSignedRequest(resUrl, claims, session, true);
conn.accept(HttpURLConnection.HTTP_OK);
} catch (CertificateEncodingException ex) {
throw new AcmeProtocolException("Invalid certificate", ex);
}

View File

@ -15,7 +15,6 @@ package org.shredzone.acme4j;
import static java.util.stream.Collectors.toList;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Instant;
import java.util.List;
@ -153,7 +152,6 @@ public class Order extends AcmeResource {
claims.putBase64("csr", csr);
conn.sendSignedRequest(getFinalizeLocation(), claims, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
}
loaded = false; // invalidate this object
}
@ -173,7 +171,6 @@ public class Order extends AcmeResource {
LOG.debug("update");
try (Connection conn = getSession().provider().connect()) {
conn.sendRequest(getLocation(), getSession());
conn.accept(HttpURLConnection.HTTP_OK);
JSON json = conn.readJsonResponse();
unmarshal(json);

View File

@ -148,8 +148,7 @@ public class OrderBuilder {
claims.put("notAfter", notAfter);
}
conn.sendSignedRequest(session.resourceUrl(Resource.NEW_ORDER), claims, session);
conn.accept(HttpURLConnection.HTTP_CREATED);
conn.sendSignedRequest(session.resourceUrl(Resource.NEW_ORDER), claims, session, HttpURLConnection.HTTP_CREATED);
JSON json = conn.readJsonResponse();

View File

@ -15,7 +15,6 @@ package org.shredzone.acme4j.challenge;
import static java.util.stream.Collectors.toList;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Instant;
import java.util.Collections;
@ -84,7 +83,6 @@ public class Challenge extends AcmeResource {
LOG.debug("bind");
try (Connection conn = session.provider().connect()) {
conn.sendRequest(location, session);
conn.accept(HttpURLConnection.HTTP_OK);
JSON json = conn.readJsonResponse();
if (!(json.contains(KEY_TYPE))) {
@ -218,7 +216,6 @@ public class Challenge extends AcmeResource {
respond(claims);
conn.sendSignedRequest(getLocation(), claims, getSession());
conn.accept(HttpURLConnection.HTTP_OK);
unmarshall(conn.readJsonResponse());
}
@ -238,7 +235,6 @@ public class Challenge extends AcmeResource {
LOG.debug("update");
try (Connection conn = getSession().provider().connect()) {
conn.sendRequest(getLocation(), getSession());
conn.accept(HttpURLConnection.HTTP_OK);
unmarshall(conn.readJsonResponse());

View File

@ -13,6 +13,7 @@
*/
package org.shredzone.acme4j.connector;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.Collection;
@ -39,6 +40,9 @@ public interface Connection extends AutoCloseable {
/**
* Sends a simple GET request.
* <p>
* If the response code was not {@link HttpURLConnection#HTTP_OK}, an
* {@link AcmeException} matching the error is raised.
*
* @param url
* {@link URL} to send the request to.
@ -57,12 +61,19 @@ public interface Connection extends AutoCloseable {
* {@link JSONBuilder} containing claims. Must not be {@code null}.
* @param session
* {@link Session} instance to be used for signing and tracking
* @param httpStatus
* Acceptable HTTP states. 200 OK if empty.
* @return HTTP 200 class status that was returned
*/
void sendSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException;
int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus)
throws AcmeException;
/**
* Sends a signed POST request. If the session's KeyIdentifier is set, a "kid"
* protected header field is sent. If not, a "jwk" protected header field is sent.
* <p>
* If the server does not return a 200 class status code, an {@link AcmeException} is
* raised matching the error.
*
* @param url
* {@link URL} to send the request to.
@ -74,19 +85,12 @@ public interface Connection extends AutoCloseable {
* {@code true} to enforce a "jwk" header field even if a KeyIdentifier is
* set, {@code false} to choose between "kid" and "jwk" header field
* automatically
*/
void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
throws AcmeException;
/**
* Checks if the HTTP response status is in the given list of acceptable HTTP states,
* otherwise raises an {@link AcmeException} matching the error.
*
* @param httpStatus
* Acceptable HTTP states
* @return Actual HTTP status that was accepted
* Acceptable HTTP states. 200 OK if empty.
* @return HTTP 200 class status that was returned
*/
int accept(int... httpStatus) throws AcmeException;
int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus)
throws AcmeException;
/**
* Reads a server response as JSON data.

View File

@ -35,7 +35,6 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -78,6 +77,9 @@ public class DefaultConnection implements Connection {
private static final Pattern BASE64URL_PATTERN = Pattern.compile("[0-9A-Za-z_-]+");
private static final URI BAD_NONCE_ERROR = URI.create("urn:ietf:params:acme:error:badNonce");
private static final int MAX_ATTEMPTS = 10;
protected final HttpConnector httpConnector;
protected HttpURLConnection conn;
@ -107,8 +109,7 @@ public class DefaultConnection implements Connection {
int rc = conn.getResponseCode();
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_NO_CONTENT) {
throw new AcmeProtocolException("Fetching a nonce returned " + rc + " "
+ conn.getResponseMessage());
throwAcmeException();
}
updateSession(session);
@ -141,108 +142,49 @@ public class DefaultConnection implements Connection {
conn.connect();
logHeaders();
int rc = conn.getResponseCode();
if (rc != HttpURLConnection.HTTP_OK) {
throwAcmeException();
}
} catch (IOException ex) {
throw new AcmeNetworkException(ex);
}
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) throws AcmeException {
if (session.getKeyIdentifier() == null) {
throw new IllegalStateException("session has no KeyIdentifier set");
}
sendSignedRequest(url, claims, session, false);
return sendSignedRequest(url, claims, session, false, httpStatus);
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus)
throws AcmeException {
Objects.requireNonNull(url, "url");
Objects.requireNonNull(claims, "claims");
Objects.requireNonNull(session, "session");
assertConnectionIsClosed();
try {
KeyPair keypair = session.getKeyPair();
AcmeException lastException = null;
if (session.getNonce() == null) {
resetNonce(session);
for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
try {
return performRequest(url, claims, session, enforceJwk, httpStatus);
} catch (AcmeServerException ex) {
if (!BAD_NONCE_ERROR.equals(ex.getType())) {
throw ex;
}
lastException = ex;
LOG.info("Bad Replay Nonce, trying again (attempt {}/{})", attempt, MAX_ATTEMPTS);
}
conn = httpConnector.openConnection(url);
conn.setRequestMethod("POST");
conn.setRequestProperty(ACCEPT_HEADER, "application/json");
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
conn.setRequestProperty(CONTENT_TYPE_HEADER, "application/jose+json");
conn.setDoOutput(true);
final PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(keypair.getPublic());
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(claims.toString());
jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce()));
jws.getHeaders().setObjectHeaderValue("url", url);
if (enforceJwk || session.getKeyIdentifier() == null) {
jws.getHeaders().setJwkHeaderValue("jwk", jwk);
} else {
jws.getHeaders().setObjectHeaderValue("kid", session.getKeyIdentifier());
}
jws.setAlgorithmHeaderValue(keyAlgorithm(jwk));
jws.setKey(keypair.getPrivate());
jws.sign();
if (LOG.isDebugEnabled()) {
LOG.debug("POST {}", url);
LOG.debug(" Payload: {}", claims.toString());
LOG.debug(" JWS Header: {}", jws.getHeaders().getFullHeaderAsJsonString());
}
JSONBuilder jb = new JSONBuilder();
jb.put("protected", jws.getHeaders().getEncodedHeader());
jb.put("payload", jws.getEncodedPayload());
jb.put("signature", jws.getEncodedSignature());
byte[] outputData = jb.toString().getBytes(DEFAULT_CHARSET);
conn.setFixedLengthStreamingMode(outputData.length);
conn.connect();
try (OutputStream out = conn.getOutputStream()) {
out.write(outputData);
}
logHeaders();
updateSession(session);
} catch (IOException ex) {
throw new AcmeNetworkException(ex);
} catch (JoseException ex) {
throw new AcmeProtocolException("Failed to generate a JSON request", ex);
}
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertConnectionIsOpen();
try {
int rc = conn.getResponseCode();
OptionalInt match = Arrays.stream(httpStatus).filter(s -> s == rc).findFirst();
if (match.isPresent()) {
return match.getAsInt();
}
String contentType = AcmeUtils.getContentType(conn.getHeaderField(CONTENT_TYPE_HEADER));
if (!"application/problem+json".equals(contentType)) {
throw new AcmeException("HTTP " + rc + ": " + conn.getResponseMessage());
}
Problem problem = new Problem(readJsonResponse(), conn.getURL());
throw createAcmeException(problem);
} catch (IOException ex) {
throw new AcmeNetworkException(ex);
}
throw new AcmeException("Too many reattempts", lastException);
}
@Override
@ -345,6 +287,91 @@ public class DefaultConnection implements Connection {
conn = null;
}
/**
* Performs the POST request.
*
* @param url
* {@link URL} to send the request to.
* @param claims
* {@link JSONBuilder} containing claims. Must not be {@code null}.
* @param session
* {@link Session} instance to be used for signing and tracking
* @param enforceJwk
* {@code true} to enforce a "jwk" header field even if a KeyIdentifier is
* set, {@code false} to choose between "kid" and "jwk" header field
* automatically
* @param httpStatus
* Acceptable HTTP states. 200 OK if empty.
* @return HTTP 200 class status that was returned
*/
private int performRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus)
throws AcmeException {
try {
KeyPair keypair = session.getKeyPair();
if (session.getNonce() == null) {
resetNonce(session);
}
conn = httpConnector.openConnection(url);
conn.setRequestMethod("POST");
conn.setRequestProperty(ACCEPT_HEADER, "application/json");
conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET);
conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag());
conn.setRequestProperty(CONTENT_TYPE_HEADER, "application/jose+json");
conn.setDoOutput(true);
final PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(keypair.getPublic());
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(claims.toString());
jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce()));
jws.getHeaders().setObjectHeaderValue("url", url);
if (enforceJwk || session.getKeyIdentifier() == null) {
jws.getHeaders().setJwkHeaderValue("jwk", jwk);
} else {
jws.getHeaders().setObjectHeaderValue("kid", session.getKeyIdentifier());
}
jws.setAlgorithmHeaderValue(keyAlgorithm(jwk));
jws.setKey(keypair.getPrivate());
jws.sign();
if (LOG.isDebugEnabled()) {
LOG.debug("POST {}", url);
LOG.debug(" Payload: {}", claims.toString());
LOG.debug(" JWS Header: {}", jws.getHeaders().getFullHeaderAsJsonString());
}
JSONBuilder jb = new JSONBuilder();
jb.put("protected", jws.getHeaders().getEncodedHeader());
jb.put("payload", jws.getEncodedPayload());
jb.put("signature", jws.getEncodedSignature());
byte[] outputData = jb.toString().getBytes(DEFAULT_CHARSET);
conn.setFixedLengthStreamingMode(outputData.length);
conn.connect();
try (OutputStream out = conn.getOutputStream()) {
out.write(outputData);
}
logHeaders();
updateSession(session);
int rc = conn.getResponseCode();
if ((httpStatus.length == 0 && rc != HttpURLConnection.HTTP_OK)
|| (httpStatus.length > 0 && !Arrays.stream(httpStatus).filter(s -> s == rc).findFirst().isPresent())) {
throwAcmeException();
}
return rc;
} catch (IOException ex) {
throw new AcmeNetworkException(ex);
} catch (JoseException ex) {
throw new AcmeProtocolException("Failed to generate a JSON request", ex);
}
}
/**
* Gets the instant sent with the Retry-After header.
*/
@ -374,42 +401,52 @@ public class DefaultConnection implements Connection {
}
/**
* Handles a problem by throwing an exception. If a JSON problem was returned, an
* {@link AcmeServerException} or subtype will be thrown. Otherwise a generic
* {@link AcmeException} is thrown.
* Throws an {@link AcmeException}. This method throws an exception that tries to
* explain the error as precisely as possible.
*/
private AcmeException createAcmeException(Problem problem) {
if (problem.getType() == null) {
return new AcmeException(problem.getDetail());
private void throwAcmeException() throws AcmeException {
try {
String contentType = AcmeUtils.getContentType(conn.getHeaderField(CONTENT_TYPE_HEADER));
if (!"application/problem+json".equals(contentType)) {
throw new AcmeException("HTTP " + conn.getResponseCode() + ": " + conn.getResponseMessage());
}
Problem problem = new Problem(readJsonResponse(), conn.getURL());
if (problem.getType() == null) {
throw new AcmeException(problem.getDetail());
}
String error = AcmeUtils.stripErrorPrefix(problem.getType().toString());
if ("unauthorized".equals(error)) {
throw new AcmeUnauthorizedException(problem);
}
if ("userActionRequired".equals(error)) {
URI tos = collectLinks("terms-of-service").stream()
.findFirst()
.map(it -> {
try {
return conn.getURL().toURI().resolve(it);
} catch (URISyntaxException ex) {
throw new AcmeProtocolException("Invalid TOS URI", ex);
}
})
.orElse(null);
throw new AcmeUserActionRequiredException(problem, tos);
}
if ("rateLimited".equals(error)) {
Optional<Instant> retryAfter = getRetryAfterHeader();
Collection<URL> rateLimits = getLinks("urn:ietf:params:acme:documentation");
throw new AcmeRateLimitedException(problem, retryAfter.orElse(null), rateLimits);
}
throw new AcmeServerException(problem);
} catch (IOException ex) {
throw new AcmeNetworkException(ex);
}
String error = AcmeUtils.stripErrorPrefix(problem.getType().toString());
if ("unauthorized".equals(error)) {
return new AcmeUnauthorizedException(problem);
}
if ("userActionRequired".equals(error)) {
URI tos = collectLinks("terms-of-service").stream()
.findFirst()
.map(it -> {
try {
return conn.getURL().toURI().resolve(it);
} catch (URISyntaxException ex) {
throw new AcmeProtocolException("Invalid TOS URI", ex);
}
})
.orElse(null);
return new AcmeUserActionRequiredException(problem, tos);
}
if ("rateLimited".equals(error)) {
Optional<Instant> retryAfter = getRetryAfterHeader();
Collection<URL> rateLimits = getLinks("urn:ietf:params:acme:documentation");
return new AcmeRateLimitedException(problem, retryAfter.orElse(null), rateLimits);
}
return new AcmeServerException(problem);
}
/**

View File

@ -13,7 +13,6 @@
*/
package org.shredzone.acme4j.connector;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.Deque;
@ -141,7 +140,6 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
private void readAndQueue() throws AcmeException {
try (Connection conn = session.provider().connect()) {
conn.sendRequest(nextUrl, session);
conn.accept(HttpURLConnection.HTTP_OK);
JSON json = conn.readJsonResponse();
fillUrlList(json);

View File

@ -13,7 +13,6 @@
*/
package org.shredzone.acme4j.provider;
import java.net.HttpURLConnection;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
@ -52,7 +51,6 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
public JSON directory(Session session, URI serverUri) throws AcmeException {
try (Connection conn = connect()) {
conn.sendRequest(resolve(serverUri), session);
conn.accept(HttpURLConnection.HTTP_OK);
// use nonce header if there is one, saves a HEAD request...
conn.updateSession(session);

View File

@ -28,7 +28,6 @@ import org.jose4j.jwx.CompactSerializer;
import org.jose4j.lang.JoseException;
import org.junit.Test;
import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.provider.TestableConnectionProvider;
import org.shredzone.acme4j.toolbox.AcmeUtils;
import org.shredzone.acme4j.toolbox.JSON;
@ -52,31 +51,24 @@ public class AccountBuilderTest {
private boolean isUpdate;
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(session, is(notNullValue()));
assertThat(url, is(locationUrl));
assertThat(isUpdate, is(false));
isUpdate = true;
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus) {
assertThat(session, is(notNullValue()));
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("newAccount").toString()));
assertThat(enforceJwk, is(true));
isUpdate = false;
}
@Override
public int accept(int... httpStatus) throws AcmeException {
if (isUpdate) {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
} else {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED));
return HttpURLConnection.HTTP_CREATED;
}
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED));
return HttpURLConnection.HTTP_CREATED;
}
@Override
@ -125,7 +117,7 @@ public class AccountBuilderTest {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus) {
try {
assertThat(session, is(notNullValue()));
assertThat(url, is(resourceUrl));
@ -162,10 +154,7 @@ public class AccountBuilderTest {
ex.printStackTrace();
fail("decoding inner payload failed");
}
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED));
return HttpURLConnection.HTTP_CREATED;
}
@ -202,15 +191,11 @@ public class AccountBuilderTest {
public void testOnlyExistingRegistration() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus) {
assertThat(session, is(notNullValue()));
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("newAccountOnlyExisting").toString()));
assertThat(enforceJwk, is(true));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED));
return HttpURLConnection.HTTP_OK;
}

View File

@ -63,15 +63,14 @@ public class AccountTest {
public void testUpdateAccount() throws AcmeException, IOException, URISyntaxException {
TestableConnectionProvider provider = new TestableConnectionProvider() {
private JSON jsonResponse;
private Integer response;
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(url, is(locationUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("updateAccount").toString()));
assertThat(session, is(notNullValue()));
jsonResponse = getJSON("updateAccountResponse");
response = HttpURLConnection.HTTP_OK;
return HttpURLConnection.HTTP_OK;
}
@Override
@ -80,17 +79,7 @@ public class AccountTest {
jsonResponse = new JSONBuilder()
.array("orders", "https://example.com/acme/order/1")
.toJSON();
response = HttpURLConnection.HTTP_OK;
return;
}
response = HttpURLConnection.HTTP_NOT_FOUND;
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(response, not(nullValue()));
return response;
}
@Override
@ -137,14 +126,10 @@ public class AccountTest {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
requestWasSent.set(true);
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@ -190,14 +175,10 @@ public class AccountTest {
public void testPreAuthorizeDomain() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("newAuthorizationRequest").toString()));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED));
return HttpURLConnection.HTTP_CREATED;
}
@ -248,14 +229,11 @@ public class AccountTest {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) throws AcmeException {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("newAuthorizationRequest").toString()));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
Problem problem = TestUtils.createProblem(problemType, problemDetail, resourceUrl);
throw new AcmeServerException(problem);
}
@ -325,7 +303,7 @@ public class AccountTest {
final TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder payload, Session session) {
public int sendSignedRequest(URL url, JSONBuilder payload, Session session, int... httpStatus) {
try {
assertThat(url, is(locationUrl));
assertThat(session, is(notNullValue()));
@ -356,11 +334,8 @@ public class AccountTest {
} catch (JoseException ex) {
fail("decoding inner payload failed");
}
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@ -408,16 +383,12 @@ public class AccountTest {
public void testDeactivate() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
JSON json = claims.toJSON();
assertThat(json.get("status").asString(), is("deactivated"));
assertThat(url, is(locationUrl));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@ -442,15 +413,11 @@ public class AccountTest {
public void testModify() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(url, is(locationUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("modifyAccount").toString()));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}

View File

@ -95,12 +95,6 @@ public class AuthorizationTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateAuthorizationResponse");
@ -147,12 +141,6 @@ public class AuthorizationTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateAuthorizationResponse");
@ -199,12 +187,6 @@ public class AuthorizationTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateAuthorizationResponse");
@ -250,16 +232,12 @@ public class AuthorizationTest {
public void testDeactivate() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
JSON json = claims.toJSON();
assertThat(json.get("status").asString(), is("deactivated"));
assertThat(url, is(locationUrl));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}

View File

@ -61,12 +61,6 @@ public class CertificateTest {
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public List<X509Certificate> readCertificates() throws AcmeException {
return originalCert;
@ -138,18 +132,14 @@ public class CertificateTest {
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus) {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateRequest").toString()));
assertThat(session, is(notNullValue()));
assertThat(session.getKeyIdentifier(), is(nullValue()));
assertThat(enforceJwk, is(true));
certRequested = false;
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@ -192,17 +182,13 @@ public class CertificateTest {
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus) {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateWithReasonRequest").toString()));
assertThat(session, is(notNullValue()));
assertThat(enforceJwk, is(true));
certRequested = false;
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@ -246,18 +232,14 @@ public class CertificateTest {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus)
throws AcmeException {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("revokeCertificateWithReasonRequest").toString()));
assertThat(session, is(notNullValue()));
assertThat(session.getKeyPair(), is(certKeyPair));
assertThat(enforceJwk, is(true));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
};

View File

@ -26,7 +26,6 @@ import java.util.Arrays;
import org.junit.Test;
import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.provider.TestableConnectionProvider;
import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSONBuilder;
@ -49,14 +48,10 @@ public class OrderBuilderTest {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("requestOrderRequest").toString()));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED));
return HttpURLConnection.HTTP_CREATED;
}

View File

@ -26,7 +26,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.provider.TestableConnectionProvider;
import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSONBuilder;
@ -51,12 +50,6 @@ public class OrderTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateOrderResponse");
@ -106,12 +99,6 @@ public class OrderTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateOrderResponse");
@ -153,16 +140,12 @@ public class OrderTest {
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(url, is(finalizeUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("finalizeRequest").toString()));
assertThat(session, is(notNullValue()));
isFinalized = true;
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}

View File

@ -66,12 +66,6 @@ public class ChallengeTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateHttpChallengeResponse");
@ -165,15 +159,11 @@ public class ChallengeTest {
public void testTrigger() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus) {
assertThat(url, is(resourceUrl));
assertThat(claims.toString(), sameJSONAs(getJSON("triggerHttpChallengeRequest").toString()));
assertThat(session, is(notNullValue()));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
assertThat(httpStatus, isIntArrayContainingInAnyOrder());
return HttpURLConnection.HTTP_OK;
}
@ -207,12 +197,6 @@ public class ChallengeTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateHttpChallengeResponse");
@ -250,12 +234,6 @@ public class ChallengeTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateHttpChallengeResponse");
@ -317,12 +295,6 @@ public class ChallengeTest {
assertThat(url, is(locationUrl));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
return getJSON("updateAccountResponse");

View File

@ -111,16 +111,14 @@ public class DefaultConnectionTest {
*/
@Test
public void testGetNonceFromHeader() {
byte[] nonce = "foo-nonce-foo".getBytes();
when(mockUrlConnection.getHeaderField("Replay-Nonce"))
.thenReturn(Base64Url.encode(nonce));
.thenReturn(Base64Url.encode(TestUtils.DUMMY_NONCE));
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.conn = mockUrlConnection;
conn.updateSession(session);
}
assertThat(session.getNonce(), is(nonce));
assertThat(session.getNonce(), is(TestUtils.DUMMY_NONCE));
verify(mockUrlConnection).getHeaderField("Replay-Nonce");
verifyNoMoreInteractions(mockUrlConnection);
@ -154,8 +152,6 @@ public class DefaultConnectionTest {
*/
@Test
public void testResetNonce() throws AcmeException, IOException {
byte[] nonce = "foo-nonce-foo".getBytes();
when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce")))
.thenReturn(mockUrlConnection);
when(mockUrlConnection.getResponseCode())
@ -173,13 +169,13 @@ public class DefaultConnectionTest {
assertThat(session.getNonce(), is(nullValue()));
when(mockUrlConnection.getHeaderField("Replay-Nonce"))
.thenReturn(Base64Url.encode(nonce));
.thenReturn(Base64Url.encode(TestUtils.DUMMY_NONCE));
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.resetNonce(session);
}
assertThat(session.getNonce(), is(nonce));
assertThat(session.getNonce(), is(TestUtils.DUMMY_NONCE));
verify(mockUrlConnection, atLeastOnce()).setRequestMethod("HEAD");
verify(mockUrlConnection, atLeastOnce()).setRequestProperty("Accept-Language", "ja-JP");
@ -404,15 +400,17 @@ public class DefaultConnectionTest {
@Test
public void testAccept() throws Exception {
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
when(mockUrlConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream());
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.conn = mockUrlConnection;
int rc = conn.accept(HttpURLConnection.HTTP_OK);
int rc = conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
assertThat(rc, is(HttpURLConnection.HTTP_OK));
}
verify(mockUrlConnection).getResponseCode();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -424,12 +422,15 @@ public class DefaultConnectionTest {
when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/problem+json");
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN);
when(mockUrlConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream());
when(mockUrlConnection.getErrorStream()).thenReturn(new ByteArrayInputStream(jsonData.getBytes("utf-8")));
when(mockUrlConnection.getURL()).thenReturn(url("https://example.com/acme/1"));
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.conn = mockUrlConnection;
conn.accept(HttpURLConnection.HTTP_OK);
conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
fail("Expected to fail");
} catch (AcmeUnauthorizedException ex) {
assertThat(ex.getType(), is(URI.create("urn:ietf:params:acme:error:unauthorized")));
@ -442,7 +443,6 @@ public class DefaultConnectionTest {
verify(mockUrlConnection, atLeastOnce()).getResponseCode();
verify(mockUrlConnection).getErrorStream();
verify(mockUrlConnection).getURL();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -458,12 +458,15 @@ public class DefaultConnectionTest {
when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/problem+json");
when(mockUrlConnection.getHeaderFields()).thenReturn(linkHeader);
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN);
when(mockUrlConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream());
when(mockUrlConnection.getErrorStream()).thenReturn(new ByteArrayInputStream(jsonData.getBytes("utf-8")));
when(mockUrlConnection.getURL()).thenReturn(url("https://example.com/acme/1"));
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.conn = mockUrlConnection;
conn.accept(HttpURLConnection.HTTP_OK);
conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
fail("Expected to fail");
} catch (AcmeUserActionRequiredException ex) {
assertThat(ex.getType(), is(URI.create("urn:ietf:params:acme:error:userActionRequired")));
@ -478,7 +481,6 @@ public class DefaultConnectionTest {
verify(mockUrlConnection, atLeastOnce()).getResponseCode();
verify(mockUrlConnection).getErrorStream();
verify(mockUrlConnection, atLeastOnce()).getURL();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -498,12 +500,15 @@ public class DefaultConnectionTest {
when(mockUrlConnection.getHeaderFieldDate("Retry-After", 0L)).thenReturn(retryAfter.toEpochMilli());
when(mockUrlConnection.getHeaderFields()).thenReturn(linkHeader);
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN);
when(mockUrlConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream());
when(mockUrlConnection.getErrorStream()).thenReturn(new ByteArrayInputStream(jsonData.getBytes("utf-8")));
when(mockUrlConnection.getURL()).thenReturn(url("https://example.com/acme/1"));
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.conn = mockUrlConnection;
conn.accept(HttpURLConnection.HTTP_OK);
conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
fail("Expected to fail");
} catch (AcmeRateLimitedException ex) {
assertThat(ex.getType(), is(URI.create("urn:ietf:params:acme:error:rateLimited")));
@ -523,7 +528,6 @@ public class DefaultConnectionTest {
verify(mockUrlConnection, atLeastOnce()).getResponseCode();
verify(mockUrlConnection).getErrorStream();
verify(mockUrlConnection, atLeastOnce()).getURL();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -537,6 +541,11 @@ public class DefaultConnectionTest {
.thenReturn(HttpURLConnection.HTTP_INTERNAL_ERROR);
when(mockUrlConnection.getURL())
.thenReturn(url("https://example.com/acme/1"));
when(mockUrlConnection.getOutputStream())
.thenReturn(new ByteArrayOutputStream());
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection) {
@Override
@ -547,8 +556,7 @@ public class DefaultConnectionTest {
return result.toJSON();
};
}) {
conn.conn = mockUrlConnection;
conn.accept(HttpURLConnection.HTTP_OK);
conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
fail("Expected to fail");
} catch (AcmeServerException ex) {
assertThat(ex.getType(), is(URI.create("urn:zombie:error:apocalypse")));
@ -560,7 +568,6 @@ public class DefaultConnectionTest {
verify(mockUrlConnection).getHeaderField("Content-Type");
verify(mockUrlConnection, atLeastOnce()).getResponseCode();
verify(mockUrlConnection).getURL();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -574,6 +581,11 @@ public class DefaultConnectionTest {
.thenReturn(HttpURLConnection.HTTP_INTERNAL_ERROR);
when(mockUrlConnection.getURL())
.thenReturn(url("https://example.com/acme/1"));
when(mockUrlConnection.getOutputStream())
.thenReturn(new ByteArrayOutputStream());
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection) {
@Override
@ -581,8 +593,7 @@ public class DefaultConnectionTest {
return JSON.empty();
};
}) {
conn.conn = mockUrlConnection;
conn.accept(HttpURLConnection.HTTP_OK);
conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
fail("Expected to fail");
} catch (AcmeNetworkException ex) {
fail("Did not expect an AcmeNetworkException");
@ -593,7 +604,6 @@ public class DefaultConnectionTest {
verify(mockUrlConnection).getHeaderField("Content-Type");
verify(mockUrlConnection, atLeastOnce()).getResponseCode();
verify(mockUrlConnection).getURL();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -607,10 +617,14 @@ public class DefaultConnectionTest {
.thenReturn(HttpURLConnection.HTTP_INTERNAL_ERROR);
when(mockUrlConnection.getResponseMessage())
.thenReturn("Infernal Server Error");
when(mockUrlConnection.getOutputStream())
.thenReturn(new ByteArrayOutputStream());
session.setKeyIdentifier(keyIdentifier);
session.setNonce(TestUtils.DUMMY_NONCE);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.conn = mockUrlConnection;
conn.accept(HttpURLConnection.HTTP_OK);
conn.sendSignedRequest(requestUrl, new JSONBuilder(), session);
fail("Expected to fail");
} catch (AcmeException ex) {
assertThat(ex.getMessage(), is("HTTP 500: Infernal Server Error"));
@ -619,7 +633,6 @@ public class DefaultConnectionTest {
verify(mockUrlConnection).getHeaderField("Content-Type");
verify(mockUrlConnection, atLeastOnce()).getResponseCode();
verify(mockUrlConnection, atLeastOnce()).getResponseMessage();
verifyNoMoreInteractions(mockUrlConnection);
}
/**
@ -627,6 +640,8 @@ public class DefaultConnectionTest {
*/
@Test
public void testSendRequest() throws Exception {
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.sendRequest(requestUrl, session);
}
@ -636,6 +651,7 @@ public class DefaultConnectionTest {
verify(mockUrlConnection).setRequestProperty("Accept-Language", "ja-JP");
verify(mockUrlConnection).setDoOutput(false);
verify(mockUrlConnection).connect();
verify(mockUrlConnection).getResponseCode();
verify(mockUrlConnection, atLeast(0)).getHeaderFields();
verifyNoMoreInteractions(mockUrlConnection);
}
@ -649,6 +665,7 @@ public class DefaultConnectionTest {
final byte[] nonce2 = "foo-nonce-2-foo".getBytes();
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
when(mockUrlConnection.getOutputStream()).thenReturn(outputStream);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection) {
@ -686,6 +703,7 @@ public class DefaultConnectionTest {
verify(mockUrlConnection).connect();
verify(mockUrlConnection).setDoOutput(true);
verify(mockUrlConnection).setFixedLengthStreamingMode(outputStream.toByteArray().length);
verify(mockUrlConnection).getResponseCode();
verify(mockUrlConnection).getOutputStream();
verify(mockUrlConnection, atLeast(0)).getHeaderFields();
verifyNoMoreInteractions(mockUrlConnection);
@ -722,6 +740,7 @@ public class DefaultConnectionTest {
final byte[] nonce2 = "foo-nonce-2-foo".getBytes();
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
when(mockUrlConnection.getOutputStream()).thenReturn(outputStream);
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection) {
@ -758,6 +777,7 @@ public class DefaultConnectionTest {
verify(mockUrlConnection).connect();
verify(mockUrlConnection).setDoOutput(true);
verify(mockUrlConnection).setFixedLengthStreamingMode(outputStream.toByteArray().length);
verify(mockUrlConnection).getResponseCode();
verify(mockUrlConnection).getOutputStream();
verify(mockUrlConnection, atLeast(0)).getHeaderFields();
verifyNoMoreInteractions(mockUrlConnection);
@ -802,7 +822,7 @@ public class DefaultConnectionTest {
/**
* Test signed POST requests if there is no nonce.
*/
@Test(expected = AcmeProtocolException.class)
@Test(expected = AcmeException.class)
public void testSendSignedRequestNoNonce() throws Exception {
when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce")))
.thenReturn(mockUrlConnection);

View File

@ -40,18 +40,14 @@ public class DummyConnection implements Connection {
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session) {
throw new UnsupportedOperationException();
}
@Override
public void sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk)
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, int... httpStatus)
throws AcmeException {
throw new UnsupportedOperationException();
}
@Override
public int accept(int... httpStatus) throws AcmeException {
public int sendSignedRequest(URL url, JSONBuilder claims, Session session, boolean enforceJwk, int... httpStatus)
throws AcmeException {
throw new UnsupportedOperationException();
}

View File

@ -15,10 +15,9 @@ package org.shredzone.acme4j.connector;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.shredzone.acme4j.toolbox.TestUtils.*;
import static org.shredzone.acme4j.toolbox.TestUtils.url;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@ -32,7 +31,6 @@ import org.junit.Before;
import org.junit.Test;
import org.shredzone.acme4j.Authorization;
import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.provider.TestableConnectionProvider;
import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSONBuilder;
@ -140,12 +138,6 @@ public class ResourceIteratorTest {
assertThat(ix, is(greaterThanOrEqualTo(0)));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
@Override
public JSON readJsonResponse() {
int start = ix * RESOURCES_PER_PAGE;

View File

@ -20,7 +20,6 @@ import static org.mockito.Mockito.*;
import static org.shredzone.acme4j.toolbox.TestUtils.getJSON;
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean;
@ -84,7 +83,6 @@ public class AbstractAcmeProviderTest {
final Connection connection = mock(Connection.class);
final Session session = mock(Session.class);
when(connection.accept(any(Integer.class))).thenReturn(HttpURLConnection.HTTP_OK);
when(connection.readJsonResponse()).thenReturn(getJSON("directory"));
AbstractAcmeProvider provider = new AbstractAcmeProvider() {
@ -110,7 +108,6 @@ public class AbstractAcmeProviderTest {
assertThat(map.toString(), sameJSONAs(TestUtils.getJSON("directory").toString()));
verify(connection).sendRequest(testResolvedUrl, session);
verify(connection).accept(any(Integer.class));
verify(connection).updateSession(any(Session.class));
verify(connection).readJsonResponse();
verify(connection).close();

View File

@ -75,6 +75,8 @@ public final class TestUtils {
public static final String ACME_SERVER_URI = "https://example.com/acme";
public static final byte[] DUMMY_NONCE = "foo-nonce-foo".getBytes();
private TestUtils() {
// utility class without constructor
}