diff --git a/src/main/java/com/smartystreets/api/ClientBuilder.java b/src/main/java/com/smartystreets/api/ClientBuilder.java index 949187f..f1d8032 100644 --- a/src/main/java/com/smartystreets/api/ClientBuilder.java +++ b/src/main/java/com/smartystreets/api/ClientBuilder.java @@ -7,8 +7,10 @@ import java.util.Map; /** - * The ClientBuilder class helps you build a client object for one of the supported SmartyStreets APIs.
- * You can use ClientBuilder's methods to customize settings like maximum retries or timeout duration. These methods
+ * The ClientBuilder class helps you build a client object for one of the + * supported SmartyStreets APIs.
+ * You can use ClientBuilder's methods to customize settings like maximum + * retries or timeout duration. These methods
* are chainable, so you can usually get set up with one line of code. */ public class ClientBuilder { @@ -30,6 +32,7 @@ public class ClientBuilder { private Proxy proxy; private Map customHeaders; private List licenses = new ArrayList<>(); + private String ip; private ClientBuilder() { this.serializer = new SmartySerializer(); @@ -47,7 +50,8 @@ public ClientBuilder(String authId, String authToken) { } /** - * @param maxRetries The maximum number of times to retry sending the request to the API. (Default is 5) + * @param maxRetries The maximum number of times to retry sending the request to + * the API. (Default is 5) * @return Returns this to accommodate method chaining. */ public ClientBuilder retryAtMost(int maxRetries) { @@ -56,7 +60,8 @@ public ClientBuilder retryAtMost(int maxRetries) { } /** - * @param maxTimeout The maximum time (in milliseconds) to wait for a connection, and also to wait for
+ * @param maxTimeout The maximum time (in milliseconds) to wait for a + * connection, and also to wait for
* the response to be read. (Default is 10000) * @return Returns this to accommodate method chaining. */ @@ -66,7 +71,8 @@ public ClientBuilder withMaxTimeout(int maxTimeout) { } /** - * @param sender Default is a series of nested senders. See buildSender(). + * @param sender Default is a series of nested senders. See + * buildSender(). * @return Returns this to accommodate method chaining. */ public ClientBuilder withSender(Sender sender) { @@ -76,6 +82,7 @@ public ClientBuilder withSender(Sender sender) { /** * Changes the Serializer from the default SmartySerializer. + * * @param serializer An object that implements the Serializer interface. * @return Returns this to accommodate method chaining. */ @@ -86,7 +93,9 @@ public ClientBuilder withSerializer(Serializer serializer) { /** * This may be useful when using a local installation of the SmartyStreets APIs. - * @param baseUrl Defaults to the URL for the API corresponding to the Client object being built. + * + * @param baseUrl Defaults to the URL for the API corresponding to the + * Client object being built. * @return Returns this to accommodate method chaining. */ public ClientBuilder withCustomBaseUrl(String baseUrl) { @@ -96,7 +105,9 @@ public ClientBuilder withCustomBaseUrl(String baseUrl) { /** * Use this to add any additional headers you need. - * @param customHeaders A String to Object Map of header name/value pairs. + * + * @param customHeaders A String to Object Map of header name/value + * pairs. * @return Returns this to accommodate method chaining. */ public ClientBuilder withCustomHeaders(Map customHeaders) { @@ -106,6 +117,7 @@ public ClientBuilder withCustomHeaders(Map customHeaders) { /** * Use this to specify a proxy through which to send all lookups. + * * @param proxyType Choose a java.net.Proxy.Type. * @param proxyHost The host of the proxy server (do not include the port). * @param proxyPort The port on the proxy server to which you wish to connect. @@ -116,8 +128,15 @@ public ClientBuilder withProxy(Proxy.Type proxyType, String proxyHost, int proxy return this; } + public ClientBuilder withXForwardedFor(String ip) { + this.ip = ip; + return this; + } + /** - * Enables debug mode, which will print information about the HTTP request and response to the console. + * Enables debug mode, which will print information about the HTTP request and + * response to the console. + * * @return Returns this to accommodate method chaining. */ public ClientBuilder withDebug() { @@ -127,6 +146,7 @@ public ClientBuilder withDebug() { /** * Allows caller to specify licenses (aka "tracks") they wish to use. + * * @return Returns this to accommodate method chaining. */ public ClientBuilder withLicenses(List licenses) { @@ -184,23 +204,27 @@ private Sender buildSender() { return this.httpSender; Sender sender; - if (this.proxy != null) + if (this.proxy != null) { sender = new SmartySender(this.maxTimeout, this.proxy); - else + } else { sender = new SmartySender(this.maxTimeout); + } sender = new StatusCodeSender(sender); - - if (this.customHeaders != null) + if (this.ip != null) { + customHeaders.put("X-Forwarded-For", this.ip); + } + if (this.customHeaders != null) { sender = new CustomHeaderSender(this.customHeaders, sender); - - if (this.signer != null) + } + if (this.signer != null) { sender = new SigningSender(this.signer, sender); - + } sender = new URLPrefixSender(this.urlPrefix, sender); - if (this.maxRetries > 0) + if (this.maxRetries > 0) { sender = new RetrySender(this.maxRetries, new MySleeper(), new MyLogger(), sender); + } sender = new LicenseSender(this.licenses, sender); diff --git a/src/test/java/com/smartystreets/api/CustomHeaderSenderTest.java b/src/test/java/com/smartystreets/api/CustomHeaderSenderTest.java index 902c3df..40381c2 100644 --- a/src/test/java/com/smartystreets/api/CustomHeaderSenderTest.java +++ b/src/test/java/com/smartystreets/api/CustomHeaderSenderTest.java @@ -19,12 +19,10 @@ public void testAllCustomHeadersAreAddedToTheRequest() throws Exception { RequestCapturingSender inner = new RequestCapturingSender(); CustomHeaderSender sender = new CustomHeaderSender(headers, inner); Request request = new Request(); - sender.send(request); Map requestHeaders = inner.getRequest().getHeaders(); assertNotNull("There should be headers here.", requestHeaders); assertEquals(headers.get("A"), inner.getRequest().getHeaders().get("A")); - } } diff --git a/src/test/java/com/smartystreets/api/XForwardedForTest.java b/src/test/java/com/smartystreets/api/XForwardedForTest.java new file mode 100644 index 0000000..d8fc715 --- /dev/null +++ b/src/test/java/com/smartystreets/api/XForwardedForTest.java @@ -0,0 +1,29 @@ +package com.smartystreets.api; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import com.smartystreets.api.mocks.RequestCapturingSender; + +public class XForwardedForTest { + @Test + public void testAllCustomHeadersAreAddedToTheRequest() throws Exception { + HashMap headers = new HashMap<>(); + headers.put("X-Forwarded-For", "ip"); + RequestCapturingSender inner = new RequestCapturingSender(); + CustomHeaderSender sender = new CustomHeaderSender(headers, inner); + Request request = new Request(); + + sender.send(request); + + Map requestHeaders = inner.getRequest().getHeaders(); + assertNotNull("Headers here.", requestHeaders); + assertEquals(headers.get("X-Forwarded-For"), inner.getRequest().getHeaders().get("X-Forwarded-For")); + + } +}