From 57140adfdb7de957918fb7d014514d575c076583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Tue, 13 Mar 2018 22:14:05 +0100 Subject: [PATCH] Handle empty JSON responses --- .../main/java/org/shredzone/acme4j/Account.java | 15 ++++++++++++--- .../java/org/shredzone/acme4j/AccountBuilder.java | 6 +++++- .../java/org/shredzone/acme4j/Authorization.java | 5 ++++- .../java/org/shredzone/acme4j/OrderBuilder.java | 6 +++++- .../org/shredzone/acme4j/challenge/Challenge.java | 5 ++++- .../shredzone/acme4j/connector/Connection.java | 2 +- .../acme4j/connector/DefaultConnection.java | 4 ++++ .../acme4j/connector/DefaultConnectionTest.java | 8 ++++++++ 8 files changed, 43 insertions(+), 8 deletions(-) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java index 5df7326d..fe1e3ede 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java @@ -158,7 +158,10 @@ public class Account extends AcmeJsonResource { conn.sendSignedRequest(newAuthzUrl, claims, getLogin()); Authorization auth = getLogin().bindAuthorization(conn.getLocation()); - auth.setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + auth.setJSON(json); + } return auth; } } @@ -224,7 +227,10 @@ public class Account extends AcmeJsonResource { conn.sendSignedRequest(getLocation(), claims, getLogin()); - setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + setJSON(json); + } } } @@ -294,7 +300,10 @@ public class Account extends AcmeJsonResource { conn.sendSignedRequest(getLocation(), claims, getLogin()); - setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + setJSON(json); + } } } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java index 23a48964..09330fc9 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java @@ -35,6 +35,7 @@ import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.toolbox.AcmeUtils; +import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSONBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -210,7 +211,10 @@ public class AccountBuilder { URL location = conn.getLocation(); Login login = new Login(location, keyPair, session); - login.getAccount().setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + login.getAccount().setJSON(json); + } return login; } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java index c19c2f47..58010aa1 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java @@ -132,7 +132,10 @@ public class Authorization extends AcmeJsonResource { conn.sendSignedRequest(getLocation(), claims, getLogin()); - setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + setJSON(json); + } } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java index c882a26a..27befdb9 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java @@ -25,6 +25,7 @@ import java.util.Set; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.exception.AcmeException; +import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSONBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -152,7 +153,10 @@ public class OrderBuilder { conn.sendSignedRequest(session.resourceUrl(Resource.NEW_ORDER), claims, login); Order order = new Order(login, conn.getLocation()); - order.setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + order.setJSON(json); + } return order; } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java index b59ddc36..a2787513 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java @@ -145,7 +145,10 @@ public class Challenge extends AcmeJsonResource { conn.sendSignedRequest(getLocation(), claims, getLogin()); - setJSON(conn.readJsonResponse()); + JSON json = conn.readJsonResponse(); + if (json != null) { + setJSON(json); + } } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java index 056f10a2..d0c52323 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java @@ -94,7 +94,7 @@ public interface Connection extends AutoCloseable { /** * Reads a server response as JSON data. * - * @return The JSON response + * @return The JSON response, or {@code null} if the server did not provide any data. */ JSON readJsonResponse() throws AcmeException; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java index a2a910fd..430fb020 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java @@ -192,6 +192,10 @@ public class DefaultConnection implements Connection { public JSON readJsonResponse() throws AcmeException { assertConnectionIsOpen(); + if (conn.getContentLength() == 0) { + return null; + } + String contentType = AcmeUtils.getContentType(conn.getHeaderField(CONTENT_TYPE_HEADER)); if (!("application/json".equals(contentType) || "application/problem+json".equals(contentType))) { diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java index 52238cd9..da1c71ab 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java @@ -427,6 +427,7 @@ public class DefaultConnectionTest { String jsonData = "{\"type\":\"urn:ietf:params:acme:error:unauthorized\",\"detail\":\"Invalid response: 404\"}"; when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/problem+json"); + when(mockUrlConnection.getContentLength()).thenReturn(jsonData.length()); when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN); when(mockUrlConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream()); when(mockUrlConnection.getErrorStream()).thenReturn(new ByteArrayInputStream(jsonData.getBytes("utf-8"))); @@ -446,6 +447,7 @@ public class DefaultConnectionTest { verify(mockUrlConnection, atLeastOnce()).getHeaderField("Content-Type"); verify(mockUrlConnection, atLeastOnce()).getResponseCode(); + verify(mockUrlConnection).getContentLength(); verify(mockUrlConnection).getErrorStream(); verify(mockUrlConnection).getURL(); } @@ -461,6 +463,7 @@ public class DefaultConnectionTest { linkHeader.put("Link", Arrays.asList("; rel=\"terms-of-service\"")); when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/problem+json"); + when(mockUrlConnection.getContentLength()).thenReturn(jsonData.length()); when(mockUrlConnection.getHeaderFields()).thenReturn(linkHeader); when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN); when(mockUrlConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream()); @@ -484,6 +487,7 @@ public class DefaultConnectionTest { verify(mockUrlConnection, atLeastOnce()).getHeaderFields(); verify(mockUrlConnection, atLeastOnce()).getResponseCode(); verify(mockUrlConnection).getErrorStream(); + verify(mockUrlConnection).getContentLength(); verify(mockUrlConnection, atLeastOnce()).getURL(); } @@ -500,6 +504,7 @@ public class DefaultConnectionTest { Instant retryAfter = Instant.now().plusSeconds(30L).truncatedTo(ChronoUnit.MILLIS); when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/problem+json"); + when(mockUrlConnection.getContentLength()).thenReturn(jsonData.length()); when(mockUrlConnection.getHeaderField("Retry-After")).thenReturn(retryAfter.toString()); when(mockUrlConnection.getHeaderFieldDate("Retry-After", 0L)).thenReturn(retryAfter.toEpochMilli()); when(mockUrlConnection.getHeaderFields()).thenReturn(linkHeader); @@ -529,6 +534,7 @@ public class DefaultConnectionTest { verify(mockUrlConnection).getHeaderFieldDate("Retry-After", 0L); verify(mockUrlConnection, atLeastOnce()).getHeaderFields(); verify(mockUrlConnection, atLeastOnce()).getResponseCode(); + verify(mockUrlConnection).getContentLength(); verify(mockUrlConnection).getErrorStream(); verify(mockUrlConnection, atLeastOnce()).getURL(); } @@ -833,6 +839,7 @@ public class DefaultConnectionTest { String jsonData = "{\n\"foo\":123,\n\"bar\":\"a-string\"\n}\n"; when(mockUrlConnection.getHeaderField("Content-Type")).thenReturn("application/json"); + when(mockUrlConnection.getContentLength()).thenReturn(jsonData.length()); when(mockUrlConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK); when(mockUrlConnection.getInputStream()).thenReturn(new ByteArrayInputStream(jsonData.getBytes("utf-8"))); @@ -845,6 +852,7 @@ public class DefaultConnectionTest { } verify(mockUrlConnection).getHeaderField("Content-Type"); + verify(mockUrlConnection).getContentLength(); verify(mockUrlConnection).getResponseCode(); verify(mockUrlConnection).getInputStream(); verifyNoMoreInteractions(mockUrlConnection);