mirror of https://github.com/shred/acme4j
Support problem title. Enhance returned problem message.
parent
ee0f98eedb
commit
22975dc844
|
@ -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() {
|
public String getDetail() {
|
||||||
return problemJson.get("detail").asString();
|
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
|
@Override
|
||||||
public String toString() {
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class AcmeServerException extends AcmeException {
|
||||||
* {@link Problem} that caused the exception
|
* {@link Problem} that caused the exception
|
||||||
*/
|
*/
|
||||||
public AcmeServerException(Problem problem) {
|
public AcmeServerException(Problem problem) {
|
||||||
super(Objects.requireNonNull(problem).getDetail());
|
super(Objects.requireNonNull(problem).toString());
|
||||||
this.problem = problem;
|
this.problem = problem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.shredzone.acme4j.toolbox.JSON;
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
import org.shredzone.acme4j.toolbox.JSONBuilder;
|
||||||
import org.shredzone.acme4j.toolbox.TestUtils;
|
import org.shredzone.acme4j.toolbox.TestUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,11 +41,15 @@ public class ProblemTest {
|
||||||
Problem problem = new Problem(original, baseUrl);
|
Problem problem = new Problem(original, baseUrl);
|
||||||
|
|
||||||
assertThat(problem.getType(), is(URI.create("urn:ietf:params:acme:error:malformed")));
|
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.getInstance(), is(URI.create("https://example.com/documents/error.html")));
|
||||||
assertThat(problem.getDomain(), is(nullValue()));
|
assertThat(problem.getDomain(), is(nullValue()));
|
||||||
assertThat(problem.asJSON().toString(), is(sameJSONAs(original.toString())));
|
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();
|
List<Problem> subs = problem.getSubProblems();
|
||||||
assertThat(subs, not(nullValue()));
|
assertThat(subs, not(nullValue()));
|
||||||
|
@ -52,13 +57,40 @@ public class ProblemTest {
|
||||||
|
|
||||||
Problem p1 = subs.get(0);
|
Problem p1 = subs.get(0);
|
||||||
assertThat(p1.getType(), is(URI.create("urn:ietf:params:acme:error:malformed")));
|
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.getDetail(), is("Invalid underscore in DNS name \"_example.com\""));
|
||||||
assertThat(p1.getDomain(), is("_example.com"));
|
assertThat(p1.getDomain(), is("_example.com"));
|
||||||
|
assertThat(p1.toString(), is("Invalid underscore in DNS name \"_example.com\""));
|
||||||
|
|
||||||
Problem p2 = subs.get(1);
|
Problem p2 = subs.get(1);
|
||||||
assertThat(p2.getType(), is(URI.create("urn:ietf:params:acme:error:rejectedIdentifier")));
|
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.getDetail(), is("This CA will not issue for \"example.net\""));
|
||||||
assertThat(p2.getDomain(), is("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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "urn:ietf:params:acme:error:malformed",
|
"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",
|
"instance": "/documents/error.html",
|
||||||
"subproblems": [
|
"subproblems": [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue