diff --git a/config/checkstyle/checkstyle-suppressions.xml b/config/checkstyle/checkstyle-suppressions.xml index 226c90e1..37afa238 100644 --- a/config/checkstyle/checkstyle-suppressions.xml +++ b/config/checkstyle/checkstyle-suppressions.xml @@ -22,4 +22,5 @@ + diff --git a/core/src/main/java/com/mapzen/android/core/GenericHttpHandler.java b/core/src/main/java/com/mapzen/android/core/GenericHttpHandler.java index bffbe43e..60eb12f8 100644 --- a/core/src/main/java/com/mapzen/android/core/GenericHttpHandler.java +++ b/core/src/main/java/com/mapzen/android/core/GenericHttpHandler.java @@ -12,6 +12,65 @@ public interface GenericHttpHandler { String HEADER_USER_AGENT = "User-Agent"; String USER_AGENT = "android-sdk;" + MapzenManager.getSdkVersion() + ";" + Build.VERSION.RELEASE; + /** + * Log levels for http requests. + */ + enum LogLevel { + /** No logs. */ + NONE, + /** + * Logs request and response lines. + * + *

Example: + *

{@code
+     * --> POST /greeting http/1.1 (3-byte body)
+     *
+     * <-- 200 OK (22ms, 6-byte body)
+     * }
+ */ + BASIC, + /** + * Logs request and response lines and their respective headers. + * + *

Example: + *

{@code
+     * --> POST /greeting http/1.1
+     * Host: example.com
+     * Content-Type: plain/text
+     * Content-Length: 3
+     * --> END POST
+     *
+     * <-- 200 OK (22ms)
+     * Content-Type: plain/text
+     * Content-Length: 6
+     * <-- END HTTP
+     * }
+ */ + HEADERS, + /** + * Logs request and response lines and their respective headers and bodies (if present). + * + *

Example: + *

{@code
+     * --> POST /greeting http/1.1
+     * Host: example.com
+     * Content-Type: plain/text
+     * Content-Length: 3
+     *
+     * Hi?
+     * --> END POST
+     *
+     * <-- 200 OK (22ms)
+     * Content-Type: plain/text
+     * Content-Length: 6
+     *
+     * Hello!
+     * <-- END HTTP
+     * }
+ */ + BODY + } + /** * Return query parameters to be appended to every request. * @return diff --git a/core/src/main/java/com/mapzen/android/graphics/MapzenMap.java b/core/src/main/java/com/mapzen/android/graphics/MapzenMap.java index 9929243b..cf6b7912 100644 --- a/core/src/main/java/com/mapzen/android/graphics/MapzenMap.java +++ b/core/src/main/java/com/mapzen/android/graphics/MapzenMap.java @@ -931,6 +931,14 @@ public void setOverlaysEnabled(boolean transitOverlayEnabled, boolean bikeOverla mapController.updateSceneAsync(updates); } + /** + * Sets the object used to add query parameters and headers to each request. + * @param handler + */ + public void setHttpHandler(MapzenMapHttpHandler handler) { + mapController.setHttpHandler(handler.httpHandler()); + } + /** * Restores all aspects of the map EXCEPT the style, this is restored in the * {@link MapInitializer}. diff --git a/core/src/main/java/com/mapzen/android/search/MapzenSearch.java b/core/src/main/java/com/mapzen/android/search/MapzenSearch.java index a030190a..f09c604f 100644 --- a/core/src/main/java/com/mapzen/android/search/MapzenSearch.java +++ b/core/src/main/java/com/mapzen/android/search/MapzenSearch.java @@ -129,6 +129,15 @@ public void setLocationProvider(PeliasLocationProvider locationProvider) { internalSearch.setLocationProvider(locationProvider); } + /** + * Sets the router's http handler for adding custom headers and parameters to + * requests. + * @param handler + */ + public void setHttpHandler(MapzenSearchHttpHandler handler) { + internalSearch.setRequestHandler(handler.searchHandler()); + } + /** * Return the underlying {@link Pelias} object. * @return diff --git a/core/src/test/java/com/mapzen/android/graphics/MapzenMapTest.java b/core/src/test/java/com/mapzen/android/graphics/MapzenMapTest.java index 98adec81..906d3de7 100644 --- a/core/src/test/java/com/mapzen/android/graphics/MapzenMapTest.java +++ b/core/src/test/java/com/mapzen/android/graphics/MapzenMapTest.java @@ -10,6 +10,7 @@ import com.mapzen.android.graphics.model.Polygon; import com.mapzen.android.graphics.model.Polyline; import com.mapzen.android.graphics.model.WalkaboutStyle; +import com.mapzen.tangram.HttpHandler; import com.mapzen.tangram.LabelPickResult; import com.mapzen.tangram.LngLat; import com.mapzen.tangram.MapController; @@ -709,6 +710,14 @@ public void applySceneUpdates_shouldClearQueuedUpdates() throws Exception { verify(bitmapMarkerManager).restoreMarkers(); } + @Test public void setHttpHandler_shouldCallMapController() throws Exception { + MapzenMapHttpHandler mapzenMapHandler = mock(MapzenMapHttpHandler.class); + HttpHandler handler = mock(HttpHandler.class); + when(mapzenMapHandler.httpHandler()).thenReturn(handler); + map.setHttpHandler(mapzenMapHandler); + verify(mapController).setHttpHandler(handler); + } + public class TestRotateResponder implements TouchInput.RotateResponder { boolean rotated = false; diff --git a/core/src/test/java/com/mapzen/android/search/MapzenSearchTest.java b/core/src/test/java/com/mapzen/android/search/MapzenSearchTest.java index 4ea19cc1..0448f69a 100644 --- a/core/src/test/java/com/mapzen/android/search/MapzenSearchTest.java +++ b/core/src/test/java/com/mapzen/android/search/MapzenSearchTest.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -85,6 +86,15 @@ public class MapzenSearchTest { verify(search.getPelias()).setLocationProvider(provider); } + @Test public void setHttpHandler_shouldCallInternalSearch() throws Exception { + MapzenSearchHttpHandler mapzenSearchHandler = mock(MapzenSearchHttpHandler.class); + MapzenSearchHttpHandler.SearchRequestHandler handler = mock( + MapzenSearchHttpHandler.SearchRequestHandler.class); + when(mapzenSearchHandler.searchHandler()).thenReturn(handler); + search.setHttpHandler(mapzenSearchHandler); + verify(search.getPelias()).setRequestHandler(handler); + } + private class TestCallback implements Callback { @Override public void onResponse(Call call, Response response) { } diff --git a/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouter.java b/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouter.java index c1b60d86..443ba26a 100644 --- a/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouter.java +++ b/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouter.java @@ -150,6 +150,15 @@ public MapzenRouter clearLocations() { return this; } + /** + * Sets the router's http handler for adding custom headers and parameters to + * requests. + * @param handler + */ + public void setHttpHandler(MapzenRouterHttpHandler handler) { + internalRouter.setHttpHandler(handler.turnByTurnHandler()); + } + public Router getRouter() { return internalRouter; } diff --git a/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouterHttpHandler.java b/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouterHttpHandler.java index a160819b..d33630e3 100644 --- a/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouterHttpHandler.java +++ b/mapzen-android-sdk/src/main/java/com/mapzen/android/routing/MapzenRouterHttpHandler.java @@ -7,6 +7,10 @@ import java.util.HashMap; import java.util.Map; +import static com.mapzen.android.core.GenericHttpHandler.LogLevel.BASIC; +import static com.mapzen.android.core.GenericHttpHandler.LogLevel.BODY; +import static com.mapzen.android.core.GenericHttpHandler.LogLevel.HEADERS; +import static com.mapzen.android.core.GenericHttpHandler.LogLevel.NONE; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.Request; @@ -18,6 +22,8 @@ */ public abstract class MapzenRouterHttpHandler implements GenericHttpHandler { + public static final String DEFAULT_URL = "https://valhalla.mapzen.com/"; + public static final LogLevel DEFAULT_LOG_LEVEL = MapzenRouterHttpHandler.getDefaultLogLevel(); private TurnByTurnHttpHandler handler; ChainProceder chainProceder = new ChainProceder(); @@ -25,7 +31,14 @@ public abstract class MapzenRouterHttpHandler implements GenericHttpHandler { * Construct handler with default url and log levels. */ public MapzenRouterHttpHandler() { - handler = new TurnByTurnHttpHandler(HttpLoggingInterceptor.Level.BODY); + handler = new TurnByTurnHttpHandler(DEFAULT_URL, DEFAULT_LOG_LEVEL); + } + + /** + * Construct handler with custom url and log levels. + */ + public MapzenRouterHttpHandler(String url, LogLevel logLevel) { + handler = new TurnByTurnHttpHandler(url, logLevel); } /** @@ -36,6 +49,10 @@ TurnByTurnHttpHandler turnByTurnHandler() { return handler; } + private static LogLevel getDefaultLogLevel() { + return BASIC; + } + /** * Handles appending api keys for all turn-by-turn requests. */ @@ -45,32 +62,20 @@ class TurnByTurnHttpHandler extends HttpHandler { private String apiKey; - /** - * Construct handler with default url and log levels. - */ - public TurnByTurnHttpHandler() { - configure(DEFAULT_URL, DEFAULT_LOG_LEVEL); - } - - /** - * Construct handler with url and default log levels. - */ - public TurnByTurnHttpHandler(String endpoint) { - configure(endpoint, DEFAULT_LOG_LEVEL); - } - - /** - * Construct handler with log levels and default url. - */ - public TurnByTurnHttpHandler(HttpLoggingInterceptor.Level logLevel) { - configure(DEFAULT_URL, logLevel); - } + private final Map TO_INTERNAL_LEVEL = new HashMap() { + { + put(NONE, HttpLoggingInterceptor.Level.NONE); + put(BASIC, HttpLoggingInterceptor.Level.BASIC); + put(HEADERS, HttpLoggingInterceptor.Level.HEADERS); + put(BODY, HttpLoggingInterceptor.Level.BODY); + } + }; /** * Construct handler with url and log levels. */ - public TurnByTurnHttpHandler(String endpoint, HttpLoggingInterceptor.Level logLevel) { - configure(endpoint, logLevel); + public TurnByTurnHttpHandler(String endpoint, LogLevel logLevel) { + configure(endpoint, TO_INTERNAL_LEVEL.get(logLevel)); } /** diff --git a/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterHttpHandlerTest.java b/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterHttpHandlerTest.java index 724f23ac..e0679bf9 100644 --- a/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterHttpHandlerTest.java +++ b/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterHttpHandlerTest.java @@ -1,5 +1,8 @@ package com.mapzen.android.routing; +import com.mapzen.android.core.GenericHttpHandler; +import com.mapzen.valhalla.TestHttpHandlerHelper; + import org.junit.Test; import java.util.HashMap; @@ -9,6 +12,8 @@ import static com.mapzen.android.core.GenericHttpHandler.USER_AGENT; import static com.mapzen.android.routing.MapzenRouterHttpHandler.TurnByTurnHttpHandler.NAME_API_KEY; import okhttp3.Interceptor; +import okhttp3.logging.HttpLoggingInterceptor; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -64,4 +69,22 @@ public class MapzenRouterHttpHandlerTest { verify(proceder).proceed(chain, params, headers); } + + @Test public void initWithCustomUrlAndLogLevelShouldCallConstructor() throws Exception { + MapzenRouterHttpHandler handler = new MapzenRouterHttpHandler("http://test.com", + GenericHttpHandler.LogLevel.BODY) { + @Override public Map queryParamsForRequest() { + return null; + } + + @Override public Map headersForRequest() { + return null; + } + }; + String endpoint = TestHttpHandlerHelper.getEndpoint(handler.turnByTurnHandler()); + assertThat(endpoint).isEqualTo("http://test.com"); + HttpLoggingInterceptor.Level level = TestHttpHandlerHelper.getLogLevel( + handler.turnByTurnHandler()); + assertThat(level).isEqualTo(HttpLoggingInterceptor.Level.BODY); + } } diff --git a/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterTest.java b/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterTest.java index 632cb11e..2ae2648a 100644 --- a/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterTest.java +++ b/mapzen-android-sdk/src/test/java/com/mapzen/android/routing/MapzenRouterTest.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class MapzenRouterTest { @@ -96,6 +97,15 @@ public class MapzenRouterTest { assertThat(MapzenRouter.DistanceUnits.KILOMETERS.toString()).isEqualTo("kilometers"); } + @Test public void setHttpHandler_shouldCallInternalRouter() throws Exception { + MapzenRouterHttpHandler mapzenRouterHandler = mock(MapzenRouterHttpHandler.class); + MapzenRouterHttpHandler.TurnByTurnHttpHandler handler = mock( + MapzenRouterHttpHandler.TurnByTurnHttpHandler.class); + when(mapzenRouterHandler.turnByTurnHandler()).thenReturn(handler); + router.setHttpHandler(mapzenRouterHandler); + verify(router.getRouter()).setHttpHandler(handler); + } + class TestRouteCallback implements RouteCallback { @Override public void success(Route route) { diff --git a/mapzen-android-sdk/src/test/java/com/mapzen/valhalla/TestHttpHandlerHelper.java b/mapzen-android-sdk/src/test/java/com/mapzen/valhalla/TestHttpHandlerHelper.java new file mode 100644 index 00000000..f1b82cca --- /dev/null +++ b/mapzen-android-sdk/src/test/java/com/mapzen/valhalla/TestHttpHandlerHelper.java @@ -0,0 +1,19 @@ +package com.mapzen.valhalla; + + +import okhttp3.logging.HttpLoggingInterceptor; + +/** + * Used to get access to internal variables for + * {@link com.mapzen.android.routing.MapzenRouterHttpHandlerTest}. + */ +public class TestHttpHandlerHelper { + + public static String getEndpoint(HttpHandler httpHandler) { + return httpHandler.endpoint; + } + + public static HttpLoggingInterceptor.Level getLogLevel(HttpHandler httpHandler) { + return httpHandler.logLevel; + } +}