Add support for Accept-Language header

pull/30/head
Richard Körber 2016-10-05 00:14:53 +02:00
parent d07e9256e7
commit 1488377e28
17 changed files with 54 additions and 24 deletions

View File

@ -178,7 +178,7 @@ public class Authorization extends AcmeResource {
public void update() throws AcmeException { public void update() throws AcmeException {
LOG.debug("update"); LOG.debug("update");
try (Connection conn = getSession().provider().connect()) { try (Connection conn = getSession().provider().connect()) {
int rc = conn.sendRequest(getLocation()); int rc = conn.sendRequest(getLocation(), getSession());
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
conn.throwAcmeException(); conn.throwAcmeException();
} }

View File

@ -90,7 +90,7 @@ public class Certificate extends AcmeResource {
if (cert == null) { if (cert == null) {
LOG.debug("download"); LOG.debug("download");
try (Connection conn = getSession().provider().connect()) { try (Connection conn = getSession().provider().connect()) {
int rc = conn.sendRequest(getLocation()); int rc = conn.sendRequest(getLocation(), getSession());
if (rc == HttpURLConnection.HTTP_ACCEPTED) { if (rc == HttpURLConnection.HTTP_ACCEPTED) {
Date retryAfter = conn.getRetryAfterHeader(); Date retryAfter = conn.getRetryAfterHeader();
if (retryAfter != null) { if (retryAfter != null) {
@ -139,7 +139,7 @@ public class Certificate extends AcmeResource {
URI link = chainCertUri; URI link = chainCertUri;
while (link != null && certChain.size() < MAX_CHAIN_LENGTH) { while (link != null && certChain.size() < MAX_CHAIN_LENGTH) {
try (Connection conn = getSession().provider().connect()) { try (Connection conn = getSession().provider().connect()) {
int rc = conn.sendRequest(chainCertUri); int rc = conn.sendRequest(chainCertUri, getSession());
if (rc != HttpURLConnection.HTTP_OK) { if (rc != HttpURLConnection.HTTP_OK) {
conn.throwAcmeException(); conn.throwAcmeException();
} }

View File

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
@ -46,6 +47,7 @@ public class Session {
private byte[] nonce; private byte[] nonce;
private Map<String, Object> directoryMap; private Map<String, Object> directoryMap;
private Metadata metadata; private Metadata metadata;
private Locale locale = Locale.getDefault();
protected Date directoryCacheExpiry; protected Date directoryCacheExpiry;
/** /**
@ -116,6 +118,21 @@ public class Session {
this.nonce = nonce; this.nonce = nonce;
} }
/**
* Gets the current locale of this session.
*/
public Locale getLocale() {
return locale;
}
/**
* Sets the locale used in this session. The locale is passed to the server as
* Accept-Language header. The server <em>may</em> respond with localized messages.
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
/** /**
* Returns the {@link AcmeProvider} that is used for this session. * Returns the {@link AcmeProvider} that is used for this session.
* <p> * <p>

View File

@ -77,7 +77,7 @@ public class Challenge extends AcmeResource {
LOG.debug("bind"); LOG.debug("bind");
try (Connection conn = session.provider().connect()) { try (Connection conn = session.provider().connect()) {
int rc = conn.sendRequest(location); int rc = conn.sendRequest(location, session);
if (rc != HttpURLConnection.HTTP_ACCEPTED) { if (rc != HttpURLConnection.HTTP_ACCEPTED) {
conn.throwAcmeException(); conn.throwAcmeException();
} }
@ -238,7 +238,7 @@ public class Challenge extends AcmeResource {
public void update() throws AcmeException { public void update() throws AcmeException {
LOG.debug("update"); LOG.debug("update");
try (Connection conn = getSession().provider().connect()) { try (Connection conn = getSession().provider().connect()) {
int rc = conn.sendRequest(getLocation()); int rc = conn.sendRequest(getLocation(), getSession());
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) { if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_ACCEPTED) {
conn.throwAcmeException(); conn.throwAcmeException();
} }

View File

@ -35,9 +35,11 @@ public interface Connection extends AutoCloseable {
* *
* @param uri * @param uri
* {@link URI} to send the request to. * {@link URI} to send the request to.
* @param session
* {@link Session} instance to be used for tracking
* @return HTTP response code * @return HTTP response code
*/ */
int sendRequest(URI uri) throws IOException; int sendRequest(URI uri, Session session) throws IOException;
/** /**
* Sends a signed POST request. * Sends a signed POST request.

View File

@ -77,10 +77,13 @@ public class DefaultConnection implements Connection {
} }
@Override @Override
public int sendRequest(URI uri) throws IOException { public int sendRequest(URI uri, Session session) throws IOException {
if (uri == null) { if (uri == null) {
throw new NullPointerException("uri must not be null"); throw new NullPointerException("uri must not be null");
} }
if (session == null) {
throw new NullPointerException("session must not be null");
}
assertConnectionIsClosed(); assertConnectionIsClosed();
LOG.debug("GET {}", uri); LOG.debug("GET {}", uri);
@ -88,6 +91,7 @@ public class DefaultConnection implements Connection {
conn = httpConnector.openConnection(uri); conn = httpConnector.openConnection(uri);
conn.setRequestMethod("GET"); conn.setRequestMethod("GET");
conn.setRequestProperty("Accept-Charset", "utf-8"); conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("Accept-Language", session.getLocale().toLanguageTag());
conn.setDoOutput(false); conn.setDoOutput(false);
conn.connect(); conn.connect();
@ -117,6 +121,7 @@ public class DefaultConnection implements Connection {
LOG.debug("Getting initial nonce, HEAD {}", uri); LOG.debug("Getting initial nonce, HEAD {}", uri);
conn = httpConnector.openConnection(uri); conn = httpConnector.openConnection(uri);
conn.setRequestMethod("HEAD"); conn.setRequestMethod("HEAD");
conn.setRequestProperty("Accept-Language", session.getLocale().toLanguageTag());
conn.connect(); conn.connect();
updateSession(session); updateSession(session);
conn = null; conn = null;
@ -132,6 +137,7 @@ public class DefaultConnection implements Connection {
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json"); conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Accept-Charset", "utf-8"); conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("Accept-Language", session.getLocale().toLanguageTag());
conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true); conn.setDoOutput(true);

View File

@ -147,7 +147,7 @@ public abstract class ResourceIterator<T extends AcmeResource> implements Iterat
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void readAndQueue() throws AcmeException { private void readAndQueue() throws AcmeException {
try (Connection conn = session.provider().connect()) { try (Connection conn = session.provider().connect()) {
int rc = conn.sendRequest(nextUri); int rc = conn.sendRequest(nextUri, session);
if (rc != HttpURLConnection.HTTP_OK) { if (rc != HttpURLConnection.HTTP_OK) {
conn.throwAcmeException(); conn.throwAcmeException();
} }

View File

@ -47,7 +47,7 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
@Override @Override
public Map<String, Object> directory(Session session, URI serverUri) throws AcmeException { public Map<String, Object> directory(Session session, URI serverUri) throws AcmeException {
try (Connection conn = connect()) { try (Connection conn = connect()) {
int rc = conn.sendRequest(resolve(serverUri)); int rc = conn.sendRequest(resolve(serverUri), session);
if (rc != HttpURLConnection.HTTP_OK) { if (rc != HttpURLConnection.HTTP_OK) {
conn.throwAcmeException(); conn.throwAcmeException();
} }

View File

@ -119,7 +119,7 @@ public class AuthorizationTest {
public void testUpdate() throws Exception { public void testUpdate() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_OK; return HttpURLConnection.HTTP_OK;
} }
@ -166,7 +166,7 @@ public class AuthorizationTest {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
requestWasSent.set(true); requestWasSent.set(true);
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_OK; return HttpURLConnection.HTTP_OK;
@ -209,7 +209,7 @@ public class AuthorizationTest {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_ACCEPTED; return HttpURLConnection.HTTP_ACCEPTED;
} }

View File

@ -52,7 +52,7 @@ public class CertificateTest {
private boolean isLocationUri; private boolean isLocationUri;
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, isOneOf(locationUri, chainUri)); assertThat(uri, isOneOf(locationUri, chainUri));
isLocationUri = uri.equals(locationUri); isLocationUri = uri.equals(locationUri);
return HttpURLConnection.HTTP_OK; return HttpURLConnection.HTTP_OK;
@ -93,7 +93,7 @@ public class CertificateTest {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_ACCEPTED; return HttpURLConnection.HTTP_ACCEPTED;
} }

View File

@ -73,7 +73,7 @@ public class RegistrationTest {
} }
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
if (URI.create("https://example.com/acme/reg/1/authz").equals(uri)) { if (URI.create("https://example.com/acme/reg/1/authz").equals(uri)) {
jsonResponse = new HashMap<>(); jsonResponse = new HashMap<>();
jsonResponse.put("authorizations", jsonResponse.put("authorizations",
@ -250,7 +250,7 @@ public class RegistrationTest {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
fail("Attempted to download the certificate. Should be downloaded already!"); fail("Attempted to download the certificate. Should be downloaded already!");
return HttpURLConnection.HTTP_OK; return HttpURLConnection.HTTP_OK;
} }

View File

@ -62,7 +62,7 @@ public class ChallengeTest {
public void testChallenge() throws Exception { public void testChallenge() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_ACCEPTED; return HttpURLConnection.HTTP_ACCEPTED;
} }
@ -175,7 +175,7 @@ public class ChallengeTest {
public void testUpdate() throws Exception { public void testUpdate() throws Exception {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_OK; return HttpURLConnection.HTTP_OK;
} }
@ -208,7 +208,7 @@ public class ChallengeTest {
TestableConnectionProvider provider = new TestableConnectionProvider() { TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
assertThat(uri, is(locationUri)); assertThat(uri, is(locationUri));
return HttpURLConnection.HTTP_ACCEPTED; return HttpURLConnection.HTTP_ACCEPTED;
} }

View File

@ -67,6 +67,7 @@ public class HttpChallengeTest {
* Test that {@link Http01Challenge} uses the given address. * Test that {@link Http01Challenge} uses the given address.
*/ */
@Test @Test
@Deprecated
public void testAddress() throws IOException { public void testAddress() throws IOException {
Http01Challenge challenge = new Http01Challenge(session); Http01Challenge challenge = new Http01Challenge(session);
challenge.unmarshall(TestUtils.getJsonAsMap("httpChallenge")); challenge.unmarshall(TestUtils.getJsonAsMap("httpChallenge"));

View File

@ -30,6 +30,7 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.jose4j.base64url.Base64Url; import org.jose4j.base64url.Base64Url;
@ -62,6 +63,7 @@ public class DefaultConnectionTest {
when(mockHttpConnection.openConnection(requestUri)).thenReturn(mockUrlConnection); when(mockHttpConnection.openConnection(requestUri)).thenReturn(mockUrlConnection);
session = TestUtils.session(); session = TestUtils.session();
session.setLocale(Locale.JAPAN);
} }
/** /**
@ -400,11 +402,12 @@ public class DefaultConnectionTest {
@Test @Test
public void testSendRequest() throws Exception { public void testSendRequest() throws Exception {
try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) {
conn.sendRequest(requestUri); conn.sendRequest(requestUri, session);
} }
verify(mockUrlConnection).setRequestMethod("GET"); verify(mockUrlConnection).setRequestMethod("GET");
verify(mockUrlConnection).setRequestProperty("Accept-Charset", "utf-8"); verify(mockUrlConnection).setRequestProperty("Accept-Charset", "utf-8");
verify(mockUrlConnection).setRequestProperty("Accept-Language", "ja-JP");
verify(mockUrlConnection).setDoOutput(false); verify(mockUrlConnection).setDoOutput(false);
verify(mockUrlConnection).connect(); verify(mockUrlConnection).connect();
verify(mockUrlConnection).getResponseCode(); verify(mockUrlConnection).getResponseCode();
@ -441,6 +444,7 @@ public class DefaultConnectionTest {
} }
verify(mockUrlConnection).setRequestMethod("HEAD"); verify(mockUrlConnection).setRequestMethod("HEAD");
verify(mockUrlConnection, times(2)).setRequestProperty("Accept-Language", "ja-JP");
verify(mockUrlConnection, times(2)).connect(); verify(mockUrlConnection, times(2)).connect();
verify(mockUrlConnection).setRequestMethod("POST"); verify(mockUrlConnection).setRequestMethod("POST");

View File

@ -30,7 +30,7 @@ import org.shredzone.acme4j.util.ClaimBuilder;
public class DummyConnection implements Connection { public class DummyConnection implements Connection {
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -133,7 +133,7 @@ public class ResourceIteratorTest {
private int ix; private int ix;
@Override @Override
public int sendRequest(URI uri) { public int sendRequest(URI uri, Session session) {
ix = pageURIs.indexOf(uri); ix = pageURIs.indexOf(uri);
assertThat(ix, is(greaterThanOrEqualTo(0))); assertThat(ix, is(greaterThanOrEqualTo(0)));
return HttpURLConnection.HTTP_OK; return HttpURLConnection.HTTP_OK;

View File

@ -83,7 +83,7 @@ public class AbstractAcmeProviderTest {
final Connection connection = mock(Connection.class); final Connection connection = mock(Connection.class);
final Session session = mock(Session.class); final Session session = mock(Session.class);
when(connection.sendRequest(testResolvedUri)).thenReturn(HttpURLConnection.HTTP_OK); when(connection.sendRequest(testResolvedUri, session)).thenReturn(HttpURLConnection.HTTP_OK);
when(connection.readJsonResponse()).thenReturn(TestUtils.getJsonAsMap("directory")); when(connection.readJsonResponse()).thenReturn(TestUtils.getJsonAsMap("directory"));
AbstractAcmeProvider provider = new AbstractAcmeProvider() { AbstractAcmeProvider provider = new AbstractAcmeProvider() {
@ -108,7 +108,7 @@ public class AbstractAcmeProviderTest {
Map<String, Object> map = provider.directory(session, testServerUri); Map<String, Object> map = provider.directory(session, testServerUri);
assertThat(JsonUtil.toJson(map), sameJSONAs(TestUtils.getJson("directory"))); assertThat(JsonUtil.toJson(map), sameJSONAs(TestUtils.getJson("directory")));
verify(connection).sendRequest(testResolvedUri); verify(connection).sendRequest(testResolvedUri, session);
verify(connection).updateSession(any(Session.class)); verify(connection).updateSession(any(Session.class));
verify(connection).readJsonResponse(); verify(connection).readJsonResponse();
verify(connection).close(); verify(connection).close();