Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extracted header-magic as enum (bunq/sdk_java#93) #102

Closed
wants to merge 8 commits into from
61 changes: 12 additions & 49 deletions src/main/java/com/bunq/sdk/http/ApiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ public class ApiClient {
* Error constants.
*/
private static final String ERROR_AMI_ENVIRONMENT_NOT_EXPECTED = "ApiEnvironment type \"%s\" is unexpected";
private static final String ERROR_COULD_NOT_DETERMINE_RESPONSE_ID = "Could not determine response id.";

/**
* Endpoints not requiring active session for the request to succeed.
Expand All @@ -61,40 +60,12 @@ public class ApiClient {
SESSION_SERVER_URL
);

/**
* Header constants.
*/
public static final String HEADER_ATTACHMENT_DESCRIPTION = "X-Bunq-Attachment-Description";
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String HEADER_USER_AGENT = "User-Agent";
public static final String HEADER_CACHE_CONTROL = "Cache-Control";
public static final String HEADER_LANGUAGE = "X-Bunq-Language";
public static final String HEADER_REGION = "X-Bunq-Region";
public static final String HEADER_REQUEST_ID = "X-Bunq-Client-Request-Id";
public static final String HEADER_GEOLOCATION = "X-Bunq-Geolocation";
private static final String HEADER_SIGNATURE = "X-Bunq-Client-Signature";
private static final String HEADER_AUTHENTICATION = "X-Bunq-Client-Authentication";
private static final String HEADER_RESPONSE_ID_LOWER_CASE = "x-bunq-client-response-id";
private static final String HEADER_RESPONSE_ID_UPPER_CASE = "X-Bunq-Client-Response-Id";

/**
* Field constants.
*/
private static final String FIELD_ERROR = "Error";
private static final String FIELD_ERROR_DESCRIPTION = "error_description";

/**
* Header value to disable the cache control.
*/
public static final String CACHE_CONTROL_NONE = "no-cache";

/**
* Prefix for bunq's own headers.
*/
private static final String USER_AGENT_BUNQ = "bunq-sdk-java/0.13.1";
public static final String LANGUAGE_EN_US = "en_US";
public static final String REGION_NL_NL = "nl_NL";
public static final String GEOLOCATION_ZERO = "0 0 0 0 000";
private static final String SCHEME_HTTPS = "https";

/**
Expand Down Expand Up @@ -193,9 +164,9 @@ public BunqResponseRaw post(

BunqRequestBody bunqRequestBody = BunqRequestBody.create(ContentType.JSON.getMediaType(), requestBodyBytes);

if (customHeaders.containsKey(HEADER_CONTENT_TYPE)) {
if (customHeaders.containsKey(BunqHeader.contentType.getHeader())) {
bunqRequestBody = BunqRequestBody.create(
MediaType.parse(customHeaders.get(HEADER_CONTENT_TYPE)),
MediaType.parse(customHeaders.get(BunqHeader.contentType.getHeader())),
requestBodyBytes
);
}
Expand Down Expand Up @@ -262,13 +233,13 @@ private void setHeaders(BunqRequestBuilder requestBuilder, Map<String, String> c

/**
*/
private void setDefaultHeaders(Request.Builder httpEntity) {
httpEntity.addHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NONE);
httpEntity.addHeader(HEADER_USER_AGENT, getVersion());
httpEntity.addHeader(HEADER_LANGUAGE, LANGUAGE_EN_US);
httpEntity.addHeader(HEADER_REGION, REGION_NL_NL);
httpEntity.addHeader(HEADER_REQUEST_ID, UUID.randomUUID().toString());
httpEntity.addHeader(HEADER_GEOLOCATION, GEOLOCATION_ZERO);
private void setDefaultHeaders(BunqRequestBuilder httpEntity) {
BunqHeader.cacheControl.addTo(httpEntity);
BunqHeader.userAgent.addTo(httpEntity);
BunqHeader.language.addTo(httpEntity);
BunqHeader.region.addTo(httpEntity);
BunqHeader.clientRequestId.addTo(httpEntity, UUID.randomUUID().toString());
BunqHeader.geolocation.addTo(httpEntity);
}

/**
Expand All @@ -285,8 +256,8 @@ private void setSessionHeaders(BunqRequestBuilder requestBuilder) {
String sessionToken = apiContext.getSessionToken();

if (sessionToken != null) {
requestBuilder.addHeader(HEADER_AUTHENTICATION, sessionToken);
requestBuilder.addHeader(HEADER_SIGNATURE, generateSignature(requestBuilder));
BunqHeader.clientAuthentication.addTo(requestBuilder, sessionToken);
BunqHeader.clientSignature.addTo(requestBuilder, generateSignature(requestBuilder));
}
}

Expand All @@ -297,12 +268,6 @@ private String generateSignature(BunqRequestBuilder requestBuilder) {
apiContext.getInstallationContext().getKeyPairClient());
}

/**
*/
private String getVersion() {
return USER_AGENT_BUNQ;
}

/**
*/
private BunqResponseRaw createBunqResponseRaw(Response response)
Expand All @@ -321,9 +286,7 @@ private BunqResponseRaw createBunqResponseRaw(Response response)
private static String getResponseId(Response response) {
Map<String, String> headerMap = getHeadersMap(response);

if (headerMap.containsKey(HEADER_RESPONSE_ID_LOWER_CASE)) {
return headerMap.get(HEADER_RESPONSE_ID_LOWER_CASE);
} else return headerMap.getOrDefault(HEADER_RESPONSE_ID_UPPER_CASE, ERROR_COULD_NOT_DETERMINE_RESPONSE_ID);
return BunqHeader.clientResponseId.getOrDefault(headerMap);
}

/**
Expand Down
62 changes: 53 additions & 9 deletions src/main/java/com/bunq/sdk/http/BunqBasicHeader.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,70 @@
package com.bunq.sdk.http;

public class BunqBasicHeader {
private String name;
private String value;
import okhttp3.Response;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class BunqBasicHeader {
/**
* String format constants for signing data
*/
public BunqBasicHeader(String name, String value) {
private static final String DELIMITER_HEADER_NAME_AND_VALUE = ": ";
private static final String NEWLINE = "\n";

private final BunqHeader name;
private final String value;

public static BunqBasicHeader get(BunqHeader header, Response response) {
return new BunqBasicHeader(header, response.header(header.getHeader()));
}

public BunqBasicHeader(BunqHeader name, String value) {
this.name = name;
this.value = value;
}

/**
*/
public String getName() {
public BunqHeader getName() {
return name;
}

/**
*/
public String getValue() {
return value;
}

private String forSigning() {
return getName().getHeader() + DELIMITER_HEADER_NAME_AND_VALUE + getValue();
}

public static String collectForSigning(
Collection<BunqBasicHeader> headers,
BunqHeader exclude,
Collection<BunqHeader> includes) {
List<String> headersForSigning = new ArrayList<String>();

for (BunqBasicHeader header:headers) {
if (!header.getName().isBunq() && !includes.contains(header.getName())) {
continue;
}

if (exclude != null && exclude.equals(header.getName())) {
continue;
}

headersForSigning.add(header.forSigning());
}

Collections.sort(headersForSigning);

StringBuffer stringBuffer = new StringBuffer();

for (String header:headersForSigning) {
stringBuffer.append(header);
stringBuffer.append(NEWLINE);
}

return stringBuffer.toString();
}
}
100 changes: 100 additions & 0 deletions src/main/java/com/bunq/sdk/http/BunqHeader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.bunq.sdk.http;

import java.util.Collection;
import java.util.Map;

public enum BunqHeader {
attachmentDescription("X-Bunq-Attachment-Description"),
cacheControl("Cache-Control", "no-cache"),
contentType("Content-Type"),
clientAuthentication("X-Bunq-Client-Authentication"),
clientEncryptionHMAC("X-Bunq-Client-Encryption-Hmac"),
clientEncryptionIV("X-Bunq-Client-Encryption-Iv"),
clientEncryptionKey("X-Bunq-Client-Encryption-Key"),
clientRequestId("X-Bunq-Client-Request-Id"),
clientSignature("X-Bunq-Client-Signature"),
clientResponseId("X-Bunq-Client-Response-Id", "Could not determine response id."),
geolocation("X-Bunq-Geolocation", "0 0 0 0 000"),
language("X-Bunq-Language", "en_US"),
region("X-Bunq-Region", "nl_NL"),
serverSignature("X-Bunq-Server-Signature"),
userAgent("User-Agent", "bunq-sdk-java/0.13.1");

private static final String PREFIX = "X-Bunq-";

private final String header;
private final String defaultValue;

BunqHeader(String header) {
this(header, null);
}

BunqHeader(String header, String defaultValue) {
this.header = header;
this.defaultValue = defaultValue;
}

public static BunqHeader parse(String value) {
for (BunqHeader header:values()) {
if (header.equals(value)) {
return header;
}
}

return null;
}

public String getHeader() {
return header;
}

public String getDefaultValue() {
return defaultValue;
}

private String getOrDefault(String value) {
if (value != null) {
return value;
}

return getDefaultValue();
}

public void addTo(Map<String, String> headers, String value) {
headers.put(getHeader(), getOrDefault(value));
}

public void addTo(BunqRequestBuilder requestBuilder) {
addTo(requestBuilder, null);
}

public void addTo(BunqRequestBuilder requestBuilder, String value) {
requestBuilder.addHeader(getHeader(), getOrDefault(value));
}

public boolean equals(String header) {
return getHeader().equalsIgnoreCase(header);
}

public boolean isBunq() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is what bunq ? Please rename to isBunqHeader

return getHeader().startsWith(PREFIX);
}

private String findKey(Collection<String> keys) {
for (String key:keys) {
if (this.equals(key)) {
return key;
}
}

return null;
}

public String getOrDefault(Map<String, String> headers) {
String key = findKey(headers.keySet());
if (key != null && headers.get(key) != null) {
return headers.get(key);
}
return getDefaultValue();
}
}
20 changes: 11 additions & 9 deletions src/main/java/com/bunq/sdk/http/BunqRequestBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,20 @@ public BunqRequestBuilder url(URL url) {
return (BunqRequestBuilder) super.url(url);
}

private void addToAllHeader(String name, String value) {
BunqHeader header = BunqHeader.parse(name);

if (header != null) {
this.allHeader.add(new BunqBasicHeader(header, value));
}
}

/**
* {@inheritDoc}
*/
@Override
public BunqRequestBuilder header(String name, String value) {
this.allHeader.add(new BunqBasicHeader(name, value));
addToAllHeader(name, value);

return (BunqRequestBuilder) super.header(name, value);
}
Expand All @@ -90,7 +98,7 @@ public BunqRequestBuilder header(String name, String value) {
*/
@Override
public BunqRequestBuilder addHeader(String name, String value) {
this.allHeader.add(new BunqBasicHeader(name, value));
addToAllHeader(name, value);

return (BunqRequestBuilder) super.addHeader(name, value);
}
Expand Down Expand Up @@ -205,13 +213,7 @@ public BunqRequestBody getBody() {

/**
*/
public List<BunqBasicHeader> getAllHeaderAsList() {
public List<BunqBasicHeader> getAllHeader() {
return this.allHeader;
}

/**
*/
public BunqBasicHeader[] getAllHeaderAsArray() {
return this.allHeader.toArray(new BunqBasicHeader[this.allHeader.size()]);
}
}
Loading