From 943f604a21a3236bf09a8ea6defd1cf0a578dfa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Wed, 16 Dec 2015 00:50:12 +0100 Subject: [PATCH] Get link relations from response header --- .../acme4j/connector/Connection.java | 9 +++++++ .../acme4j/impl/DefaultConnection.java | 21 +++++++++++++++ .../acme4j/impl/DefaultConnectionTest.java | 27 +++++++++++++++++++ 3 files changed, 57 insertions(+) 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 82752426..de387cff 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 @@ -91,6 +91,15 @@ public interface Connection extends AutoCloseable { */ URI getLocation() throws AcmeException; + /** + * Gets a link relation from the header. + * + * @param relation + * Link relation + * @return Link, or {@code null} if there was no such link relation + */ + URI getLink(String relation) throws AcmeException; + /** * Closes the {@link Connection}, releasing all resources. */ diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/impl/DefaultConnection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/impl/DefaultConnection.java index 6539cb3e..037249e5 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/impl/DefaultConnection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/impl/DefaultConnection.java @@ -26,7 +26,9 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.EnumMap; +import java.util.List; import java.util.Map; +import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jose4j.base64url.Base64Url; @@ -248,6 +250,25 @@ public class DefaultConnection implements Connection { } } + @Override + public URI getLink(String relation) throws AcmeException { + List links = conn.getHeaderFields().get("Link"); + if (links != null) { + Pattern p = Pattern.compile("<(.*?)>\\s*;\\s*rel=\"?"+ Pattern.quote(relation) + "\"?"); + for (String link : links) { + Matcher m = p.matcher(link); + if (m.matches()) { + try { + return new URI(m.group(1)); + } catch (URISyntaxException ex) { + throw new AcmeException("Bad Link header: " + link); + } + } + } + } + return null; + } + @Override public void close() { conn = null; diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/impl/DefaultConnectionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/impl/DefaultConnectionTest.java index 8f527644..208da9ce 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/impl/DefaultConnectionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/impl/DefaultConnectionTest.java @@ -27,8 +27,10 @@ import java.net.URI; import java.net.URISyntaxException; import java.security.KeyPair; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -144,6 +146,31 @@ public class DefaultConnectionTest { verifyNoMoreInteractions(mockUrlConnection); } + /** + * Test that Link headers are evaluated. + */ + @Test + public void testGetLink() throws Exception { + Map> headers = new HashMap>(); + headers.put("Content-Type", Arrays.asList("application/json")); + headers.put("Location", Arrays.asList("https://example.com/acme/reg/asdf")); + headers.put("Link", Arrays.asList( + ";rel=\"next\"", + ";rel=recover", + "; rel=\"terms-of-service\"" + )); + + when(mockUrlConnection.getHeaderFields()).thenReturn(headers); + + try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { + conn.conn = mockUrlConnection; + assertThat(conn.getLink("next"), is(new URI("https://example.com/acme/new-authz"))); + assertThat(conn.getLink("recover"), is(new URI("https://example.com/acme/recover-reg"))); + assertThat(conn.getLink("terms-of-service"), is(new URI("https://example.com/acme/terms"))); + assertThat(conn.getLink("secret-stuff"), is(nullValue())); + } + } + /** * Test that no Location header returns {@code null}. */