diff --git a/android-core/src/androidTest/kotlin/com.mparticle/networking/MParticleBaseClientImplTest.kt b/android-core/src/androidTest/kotlin/com.mparticle/networking/MParticleBaseClientImplTest.kt index 6e77389a8..91805fef0 100644 --- a/android-core/src/androidTest/kotlin/com.mparticle/networking/MParticleBaseClientImplTest.kt +++ b/android-core/src/androidTest/kotlin/com.mparticle/networking/MParticleBaseClientImplTest.kt @@ -1,11 +1,12 @@ package com.mparticle.networking +import android.net.Uri +import com.mparticle.BuildConfig import com.mparticle.MParticle import com.mparticle.MParticleOptions import com.mparticle.internal.AccessUtils import com.mparticle.internal.ConfigManager import com.mparticle.testutils.BaseCleanInstallEachTest -import junit.framework.TestCase import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Before @@ -213,8 +214,7 @@ class MParticleBaseClientImplTest : BaseCleanInstallEachTest() { val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl for (endpoint in MParticleBaseClientImpl.Endpoint.values()) { val generatedUrl = baseClientImpl.getUrl(endpoint, endpoint.name, true) - assertEquals(defaultUrls[endpoint].toString(), generatedUrl.toString()) - TestCase.assertTrue(generatedUrl === generatedUrl.defaultUrl) + assertEquals(defaultUrls[endpoint].toString(), generatedUrl.defaultUrl.toString()) } for (endpoint in MParticleBaseClientImpl.Endpoint.values()) { val generatedUrl = baseClientImpl.getUrl(endpoint, endpoint.name, false) @@ -226,4 +226,100 @@ class MParticleBaseClientImplTest : BaseCleanInstallEachTest() { ) } } + + @Test + @Throws(MalformedURLException::class) + fun testGenerateDefaultURL() { + val options = MParticleOptions.builder(mContext) + .credentials(apiKey, "secret") + .build() + MParticle.start(options) + val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl + val subdirectory = "/v2/" + val uri = Uri.Builder() + .scheme(BuildConfig.SCHEME) + .encodedAuthority("nativesdks.us1.mparticle.com") + .path("$subdirectory us1-foo/events") + .build() + val result = baseClientImpl.generateDefaultURL(uri, "nativesdks.mparticle.com", "v2/us1-akshd324uajbhg123OIASI/events") + assertEquals("https://nativesdks.mparticle.com/v2/us1-akshd324uajbhg123OIASI/events", result.toString()) + } + + @Test + @Throws(MalformedURLException::class) + fun testGenerateDefaultURL_When_defaultDomain_IS_Empty() { + val options = MParticleOptions.builder(mContext) + .credentials(apiKey, "secret") + .build() + MParticle.start(options) + val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl + val subdirectory = "/v2/" + val uri = Uri.Builder() + .scheme(BuildConfig.SCHEME) + .encodedAuthority("nativesdks.us1.mparticle.com") + .path("$subdirectory eu1-fooapi/events") + .build() + val result = baseClientImpl.generateDefaultURL(uri, "", "v2/us1-asjdjasdgjhasgdjhas/events") + assertEquals("https://nativesdks.us1.mparticle.com/v2/us1-asjdjasdgjhasgdjhas/events", result.toString()) + } + + @Test + @Throws(MalformedURLException::class) + fun testGenerateDefaultURL_When_defaultDomain_IS_NULL() { + val options = MParticleOptions.builder(mContext) + .credentials(apiKey, "secret") + .build() + MParticle.start(options) + val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl + val subdirectory = "/v2/" + val uri = Uri.Builder() + .scheme(BuildConfig.SCHEME) + .encodedAuthority("nativesdks.us1.mparticle.com") + .path("$subdirectory us1-foo/events") + .build() + val result = baseClientImpl.generateDefaultURL(uri, null, "v2/us1-asjdjasdgjhasgdjhas/events") + assertEquals("https://nativesdks.us1.mparticle.com/v2/us1-asjdjasdgjhasgdjhas/events", result.toString()) + } + + @Test + @Throws(MalformedURLException::class) + fun testGenerateDefaultURL_When_URL_IS_NULL() { + val options = MParticleOptions.builder(mContext) + .credentials(apiKey, "secret") + .build() + MParticle.start(options) + val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl + val result = baseClientImpl.generateDefaultURL(null, "nativesdks.mparticle.com", "v2/us1-bee5781b649a7a40a592c2000bc892d0/events") + assertEquals(null, result) + } + + @Test + @Throws(MalformedURLException::class) + fun testGenerateDefaultURL_When_PATH_IS_NULL() { + val options = MParticleOptions.builder(mContext) + .credentials(apiKey, "secret") + .build() + MParticle.start(options) + val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl + val subdirectory = "/v2/" + val uri = Uri.Builder() + .scheme(BuildConfig.SCHEME) + .encodedAuthority("nativesdks.us1.mparticle.com") + .path("$subdirectory us1-foo/events") + .build() + val result = baseClientImpl.generateDefaultURL(uri, "nativesdks.mparticle.com", null) + assertEquals("https://nativesdks.mparticle.com/v2/%20us1-foo/events", result.toString()) + } + + @Test + @Throws(MalformedURLException::class) + fun testGenerateDefaultURL_When_defaultDomain_AND_URL_AND_PATH_ARE_NULL() { + val options = MParticleOptions.builder(mContext) + .credentials(apiKey, "secret") + .build() + MParticle.start(options) + val baseClientImpl = AccessUtils.getApiClient() as MParticleBaseClientImpl + val result = baseClientImpl.generateDefaultURL(null, null, null) + assertEquals(null, result) + } } diff --git a/android-core/src/main/java/com/mparticle/networking/MParticleBaseClientImpl.java b/android-core/src/main/java/com/mparticle/networking/MParticleBaseClientImpl.java index c714aee5f..b59c36397 100644 --- a/android-core/src/main/java/com/mparticle/networking/MParticleBaseClientImpl.java +++ b/android-core/src/main/java/com/mparticle/networking/MParticleBaseClientImpl.java @@ -103,26 +103,37 @@ protected MPUrl getUrl(Endpoint endpoint, @Nullable String identityPath, boolean NetworkOptions networkOptions = mConfigManager.getNetworkOptions(); DomainMapping domainMapping = networkOptions.getDomain(endpoint); String url = NetworkOptionsManager.getDefaultUrl(endpoint); + // Default domain to use for URL generation when domain mapping is specified + String defaultDomain = url; boolean isDefaultUrl = true; - if (domainMapping != null && !MPUtility.isEmpty(domainMapping.getUrl()) && !forceDefaultUrl) { - String domainMappingUrl = domainMapping.getUrl(); + String domainMappingUrl = domainMapping != null ? domainMapping.getUrl() : null; + if (!MPUtility.isEmpty(domainMappingUrl)) { isDefaultUrl = url.equals(domainMappingUrl); url = domainMappingUrl; } Uri uri; - if (endpoint != Endpoint.CONFIG & isDefaultUrl) { - url = getPodUrl(url, mConfigManager.getPodPrefix(), mConfigManager.isDirectUrlRoutingEnabled()); + // If domain mapping is not specified, need to set the prefix when it is enabled in the configuration. If EndPoint is config, there's no need to set the prefix. + if (endpoint != Endpoint.CONFIG) { + if (isDefaultUrl) { + url = getPodUrl(url, mConfigManager.getPodPrefix(), mConfigManager.isDirectUrlRoutingEnabled()); + } else { + // When domain mapping is specified, generate the default domain. Whether podRedirection is enabled or not, always use the original URL. + defaultDomain = getPodUrl(defaultDomain, null, false); + } } - MPUrl defaultUrl = !isDefaultUrl ? getUrl(endpoint, identityPath, true) : null; String subdirectory; - boolean overridesSubdirectory = domainMapping.isOverridesSubdirectory() && !forceDefaultUrl; + String pathPrefix; + String pathPostfix; + boolean overridesSubdirectory = domainMapping.isOverridesSubdirectory(); switch (endpoint) { case CONFIG: - subdirectory = overridesSubdirectory ? "" : SERVICE_VERSION_4 + "/"; + pathPrefix = SERVICE_VERSION_4 + "/"; + subdirectory = overridesSubdirectory ? "" : pathPrefix; + pathPostfix = mApiKey + "/config"; Uri.Builder builder = new Uri.Builder() .scheme(BuildConfig.SCHEME) .encodedAuthority(url) - .path(subdirectory + mApiKey + "/config") + .path(subdirectory + pathPostfix) .appendQueryParameter("av", MPUtility.getAppVersionName(mContext)) .appendQueryParameter("sv", Constants.MPARTICLE_VERSION); if (mConfigManager.getDataplanId() != null) { @@ -136,43 +147,74 @@ protected MPUrl getUrl(Endpoint endpoint, @Nullable String identityPath, boolean } } } - return MPUrl.getUrl(builder.build().toString(), defaultUrl); + return MPUrl.getUrl(builder.build().toString(), !isDefaultUrl ? generateDefaultURL(builder.build(), defaultDomain, (pathPrefix + pathPostfix)) : null); case EVENTS: - subdirectory = overridesSubdirectory ? "" : SERVICE_VERSION_2 + "/"; + pathPrefix = SERVICE_VERSION_2 + "/"; + subdirectory = overridesSubdirectory ? "" : pathPrefix; + pathPostfix = mApiKey + "/events"; uri = new Uri.Builder() .scheme(BuildConfig.SCHEME) .encodedAuthority(url) - .path(subdirectory + mApiKey + "/events") + .path(subdirectory + pathPostfix) .build(); - return MPUrl.getUrl(uri.toString(), defaultUrl); + + return MPUrl.getUrl(uri.toString(), !isDefaultUrl ? generateDefaultURL(uri, defaultDomain, (pathPrefix + pathPostfix)) : null); case ALIAS: - subdirectory = overridesSubdirectory ? "" : SERVICE_VERSION_1 + "/identity/"; + pathPrefix = SERVICE_VERSION_1 + "/identity/"; + subdirectory = overridesSubdirectory ? "" : pathPrefix; + pathPostfix = mApiKey + "/alias"; uri = new Uri.Builder() .scheme(BuildConfig.SCHEME) .encodedAuthority(url) - .path(subdirectory + mApiKey + "/alias") + .path(subdirectory + pathPostfix) .build(); - return MPUrl.getUrl(uri.toString(), defaultUrl); + return MPUrl.getUrl(uri.toString(), !isDefaultUrl ? generateDefaultURL(uri, defaultDomain, (pathPrefix + pathPostfix)) : null); case IDENTITY: + pathPrefix = SERVICE_VERSION_1 + "/"; subdirectory = overridesSubdirectory ? "" : SERVICE_VERSION_1 + "/"; + pathPostfix = identityPath; uri = new Uri.Builder() .scheme(BuildConfig.SCHEME) .encodedAuthority(url) - .path(subdirectory + identityPath) + .path(subdirectory + pathPostfix) .build(); - return MPUrl.getUrl(uri.toString(), defaultUrl); + return MPUrl.getUrl(uri.toString(), !isDefaultUrl ? generateDefaultURL(uri, defaultDomain, (pathPrefix + pathPostfix)) : null); case AUDIENCE: + pathPostfix = SERVICE_VERSION_2 + "/" + mApiKey + "/audience?mpID=" + mConfigManager.getMpid(); uri = new Uri.Builder() .scheme(BuildConfig.SCHEME) .encodedAuthority(url) - .path(SERVICE_VERSION_2 + "/" + mApiKey + "/audience?mpID=" + mConfigManager.getMpid()) + .path(pathPostfix) .build(); - return MPUrl.getUrl(uri.toString(), defaultUrl); + return MPUrl.getUrl(uri.toString(), !isDefaultUrl ? generateDefaultURL(uri, defaultDomain, pathPostfix) : null); default: return null; } } + /** + * Generates a new URL using the default domain when domain mapping is specified. + * This method creates a new URI based on the existing URI, but replaces the domain with the default domain. + * + * @param uri The existing URI which includes the domain mapping. + * @param defaultDomain The default domain name to be used in the new URI. + * @param path path to be used in the new URI. + * @return A new URI with the same path and scheme as the original URI, but with the default domain. + */ + protected MPUrl generateDefaultURL(Uri uri, String defaultDomain, String path) throws MalformedURLException { + if (uri != null) { + Uri.Builder uriBuilder = Uri.parse(uri.toString()).buildUpon(); + if (defaultDomain != null && !defaultDomain.isEmpty()) { + uriBuilder.encodedAuthority(defaultDomain); + } + if (path != null && !path.isEmpty()) { + uriBuilder.path(path); + } + return MPUrl.getUrl(uriBuilder.build().toString(), null); + } + return null; + } + String getPodUrl( String URLPrefix, String pod,