Support problem title. Enhance returned problem message.

pull/55/head
Richard Körber 2017-12-22 17:33:55 +01:00
parent ee0f98eedb
commit 22975dc844
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
4 changed files with 84 additions and 7 deletions

View File

@ -62,7 +62,20 @@ public class Problem implements Serializable {
}
/**
* Returns a human-readable description of the problem.
* Returns a short, human-readable summary of the problem. The text may be localized
* if supported by the server. {@code null} if the server did not provide a title.
*
* @see #toString()
*/
public String getTitle() {
return problemJson.get("title").asString();
}
/**
* Returns a detailed and specific human-readable explanation of the problem. The
* text may be localized if supported by the server.
*
* @see #toString()
*/
public String getDetail() {
return problemJson.get("detail").asString();
@ -120,11 +133,42 @@ public class Problem implements Serializable {
}
/**
* Returns the problem as JSON string.
* Returns a human-readable description of the problem, that is as specific as
* possible. The description may be localized if supported by the server.
* <p>
* If {@link #getSubProblems()} exist, they will be appended.
* <p>
* Technically, it returns {@link #getDetail()}. If not set, {@link #getTitle()} is
* returned instead. As a last resort, {@link #getType()} is returned.
*/
@Override
public String toString() {
return problemJson.toString();
StringBuilder sb = new StringBuilder();
if (getDetail() != null) {
sb.append(getDetail());
} else if (getTitle() != null) {
sb.append(getTitle());
} else {
sb.append(getType());
}
List<Problem> subproblems = getSubProblems();
if (!subproblems.isEmpty()) {
sb.append(" (");
boolean first = true;
for (Problem sub : subproblems) {
if (!first) {
sb.append(" ");
}
sb.append(sub.toString());
first = false;
}
sb.append(')');
}
return sb.toString();
}
}

View File

@ -34,7 +34,7 @@ public class AcmeServerException extends AcmeException {
* {@link Problem} that caused the exception
*/
public AcmeServerException(Problem problem) {
super(Objects.requireNonNull(problem).getDetail());
super(Objects.requireNonNull(problem).toString());
this.problem = problem;
}

View File

@ -25,6 +25,7 @@ import java.util.List;
import org.junit.Test;
import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSONBuilder;
import org.shredzone.acme4j.toolbox.TestUtils;
/**
@ -40,11 +41,15 @@ public class ProblemTest {
Problem problem = new Problem(original, baseUrl);
assertThat(problem.getType(), is(URI.create("urn:ietf:params:acme:error:malformed")));
assertThat(problem.getDetail(), is("Some of the identifiers requested were rejected"));
assertThat(problem.getTitle(), is("Some of the identifiers requested were rejected"));
assertThat(problem.getDetail(), is("Identifier \"abc12_\" is malformed"));
assertThat(problem.getInstance(), is(URI.create("https://example.com/documents/error.html")));
assertThat(problem.getDomain(), is(nullValue()));
assertThat(problem.asJSON().toString(), is(sameJSONAs(original.toString())));
assertThat(problem.toString(), is(sameJSONAs(original.toString())));
assertThat(problem.toString(), is(
"Identifier \"abc12_\" is malformed ("
+ "Invalid underscore in DNS name \"_example.com\" "
+ "This CA will not issue for \"example.net\")"));
List<Problem> subs = problem.getSubProblems();
assertThat(subs, not(nullValue()));
@ -52,13 +57,40 @@ public class ProblemTest {
Problem p1 = subs.get(0);
assertThat(p1.getType(), is(URI.create("urn:ietf:params:acme:error:malformed")));
assertThat(p1.getTitle(), is(nullValue()));
assertThat(p1.getDetail(), is("Invalid underscore in DNS name \"_example.com\""));
assertThat(p1.getDomain(), is("_example.com"));
assertThat(p1.toString(), is("Invalid underscore in DNS name \"_example.com\""));
Problem p2 = subs.get(1);
assertThat(p2.getType(), is(URI.create("urn:ietf:params:acme:error:rejectedIdentifier")));
assertThat(p2.getTitle(), is(nullValue()));
assertThat(p2.getDetail(), is("This CA will not issue for \"example.net\""));
assertThat(p2.getDomain(), is("example.net"));
assertThat(p2.toString(), is("This CA will not issue for \"example.net\""));
}
/**
* Test that {@link Problem#toString()} always returns the most specific message.
*/
@Test
public void testToString() {
URL baseUrl = url("https://example.com/acme/1");
URI typeUri = URI.create("urn:ietf:params:acme:error:malformed");
JSONBuilder jb = new JSONBuilder();
jb.put("type", typeUri);
Problem p1 = new Problem(jb.toJSON(), baseUrl);
assertThat(p1.toString(), is(typeUri.toString()));
jb.put("title", "Some of the identifiers requested were rejected");
Problem p2 = new Problem(jb.toJSON(), baseUrl);
assertThat(p2.toString(), is("Some of the identifiers requested were rejected"));
jb.put("detail", "Identifier \"abc12_\" is malformed");
Problem p3 = new Problem(jb.toJSON(), baseUrl);
assertThat(p3.toString(), is("Identifier \"abc12_\" is malformed"));
}
}

View File

@ -1,6 +1,7 @@
{
"type": "urn:ietf:params:acme:error:malformed",
"detail": "Some of the identifiers requested were rejected",
"title": "Some of the identifiers requested were rejected",
"detail": "Identifier \"abc12_\" is malformed",
"instance": "/documents/error.html",
"subproblems": [
{