diff --git a/firebase-functions/ktx/api.txt b/firebase-functions/ktx/api.txt index 47f771d2f38..0d8eb896b78 100644 --- a/firebase-functions/ktx/api.txt +++ b/firebase-functions/ktx/api.txt @@ -3,9 +3,9 @@ package com.google.firebase.functions.ktx { public final class FunctionsKt { ctor public FunctionsKt(); - method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull String region); + method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull String regionOrCustomDomain); method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app); - method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app, @NonNull String region); + method @NonNull public static com.google.firebase.functions.FirebaseFunctions functions(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app, @NonNull String regionOrCustomDomain); method @NonNull public static com.google.firebase.functions.FirebaseFunctions getFunctions(@NonNull com.google.firebase.ktx.Firebase); } diff --git a/firebase-functions/ktx/src/main/kotlin/com/google/firebase/functions/ktx/Functions.kt b/firebase-functions/ktx/src/main/kotlin/com/google/firebase/functions/ktx/Functions.kt index c8f5e9a4d6e..5fc5ad42558 100644 --- a/firebase-functions/ktx/src/main/kotlin/com/google/firebase/functions/ktx/Functions.kt +++ b/firebase-functions/ktx/src/main/kotlin/com/google/firebase/functions/ktx/Functions.kt @@ -26,15 +26,16 @@ import com.google.firebase.platforminfo.LibraryVersionComponent val Firebase.functions: FirebaseFunctions get() = FirebaseFunctions.getInstance() -/** Returns the [FirebaseFunctions] instance of a given [region]. */ -fun Firebase.functions(region: String): FirebaseFunctions = FirebaseFunctions.getInstance(region) +/** Returns the [FirebaseFunctions] instance of a given [regionOrCustomDomain]. */ +fun Firebase.functions(regionOrCustomDomain: String): FirebaseFunctions = + FirebaseFunctions.getInstance(regionOrCustomDomain) /** Returns the [FirebaseFunctions] instance of a given [FirebaseApp]. */ fun Firebase.functions(app: FirebaseApp): FirebaseFunctions = FirebaseFunctions.getInstance(app) -/** Returns the [FirebaseFunctions] instance of a given [FirebaseApp] and [region]. */ -fun Firebase.functions(app: FirebaseApp, region: String): FirebaseFunctions = - FirebaseFunctions.getInstance(app, region) +/** Returns the [FirebaseFunctions] instance of a given [FirebaseApp] and [regionOrCustomDomain]. */ +fun Firebase.functions(app: FirebaseApp, regionOrCustomDomain: String): FirebaseFunctions = + FirebaseFunctions.getInstance(app, regionOrCustomDomain) internal const val LIBRARY_NAME: String = "fire-fun-ktx" diff --git a/firebase-functions/src/androidTest/java/com/google/firebase/functions/FirebaseFunctionsTest.java b/firebase-functions/src/androidTest/java/com/google/firebase/functions/FirebaseFunctionsTest.java index 402a859a604..45a3402ac5e 100644 --- a/firebase-functions/src/androidTest/java/com/google/firebase/functions/FirebaseFunctionsTest.java +++ b/firebase-functions/src/androidTest/java/com/google/firebase/functions/FirebaseFunctionsTest.java @@ -38,6 +38,14 @@ public void testGetUrl() { functions = FirebaseFunctions.getInstance(app); url = functions.getURL("my-endpoint"); assertEquals("https://us-central1-my-project.cloudfunctions.net/my-endpoint", url.toString()); + + functions = FirebaseFunctions.getInstance(app, "https://mydomain.com"); + url = functions.getURL("my-endpoint"); + assertEquals("https://mydomain.com/my-endpoint", url.toString()); + + functions = FirebaseFunctions.getInstance(app, "https://mydomain.com/foo"); + url = functions.getURL("my-endpoint"); + assertEquals("https://mydomain.com/foo/my-endpoint", url.toString()); } @Test @@ -57,6 +65,14 @@ public void testGetUrl_withEmulator() { URL withRegion = functionsWithRegion.getURL("my-endpoint"); assertEquals("http://10.0.2.2:5001/my-project/my-region/my-endpoint", withRegion.toString()); + + FirebaseFunctions functionsWithCustomDomain = + FirebaseFunctions.getInstance(app, "https://mydomain.com"); + functionsWithCustomDomain.useEmulator("10.0.2.2", 5001); + + URL withCustomDOmain = functionsWithCustomDomain.getURL("my-endpoint"); + assertEquals( + "http://10.0.2.2:5001/my-project/us-central1/my-endpoint", withCustomDOmain.toString()); } @Test diff --git a/firebase-functions/src/main/java/com/google/firebase/functions/FirebaseFunctions.java b/firebase-functions/src/main/java/com/google/firebase/functions/FirebaseFunctions.java index bdd96c373e2..89e0deee677 100644 --- a/firebase-functions/src/main/java/com/google/firebase/functions/FirebaseFunctions.java +++ b/firebase-functions/src/main/java/com/google/firebase/functions/FirebaseFunctions.java @@ -75,6 +75,9 @@ public class FirebaseFunctions { // The region to use for all function references. private final String region; + // A custom domain for the http trigger, such as "https://mydomain.com" + @Nullable private final String customDomain; + // The format to use for constructing urls from region, projectId, and name. private String urlFormat = "https://%1$s-%2$s.cloudfunctions.net/%3$s"; @@ -85,14 +88,29 @@ public class FirebaseFunctions { FirebaseApp app, Context context, String projectId, - String region, + String regionOrCustomDomain, ContextProvider contextProvider) { this.app = app; this.client = new OkHttpClient(); this.serializer = new Serializer(); this.contextProvider = Preconditions.checkNotNull(contextProvider); this.projectId = Preconditions.checkNotNull(projectId); - this.region = Preconditions.checkNotNull(region); + + boolean isRegion; + try { + new URL(regionOrCustomDomain); + isRegion = false; + } catch (MalformedURLException malformedURLException) { + isRegion = true; + } + + if (isRegion) { + this.region = regionOrCustomDomain; + this.customDomain = null; + } else { + this.region = "us-central1"; + this.customDomain = regionOrCustomDomain; + } maybeInstallProviders(context); } @@ -135,20 +153,22 @@ public void onProviderInstallFailed(int i, android.content.Intent intent) { } /** - * Creates a Cloud Functions client with the given app and region. + * Creates a Cloud Functions client with the given app and region or custom domain. * * @param app The app for the Firebase project. - * @param region The region for the HTTPS trigger, such as "us-central1". + * @param regionOrCustomDomain The region or custom domain for the HTTPS trigger, such as + * "us-central1" or "https://mydomain.com". */ @NonNull - public static FirebaseFunctions getInstance(@NonNull FirebaseApp app, @NonNull String region) { + public static FirebaseFunctions getInstance( + @NonNull FirebaseApp app, @NonNull String regionOrCustomDomain) { Preconditions.checkNotNull(app, "You must call FirebaseApp.initializeApp first."); - Preconditions.checkNotNull(region); + Preconditions.checkNotNull(regionOrCustomDomain); FunctionsMultiResourceComponent component = app.get(FunctionsMultiResourceComponent.class); Preconditions.checkNotNull(component, "Functions component does not exist."); - return component.get(region); + return component.get(regionOrCustomDomain); } /** @@ -162,13 +182,14 @@ public static FirebaseFunctions getInstance(@NonNull FirebaseApp app) { } /** - * Creates a Cloud Functions client with the default app and given region. + * Creates a Cloud Functions client with the default app and given region or custom domain. * - * @param region The region for the HTTPS trigger, such as "us-central1". + * @param regionOrCustomDomain The regionOrCustomDomain for the HTTPS trigger, such as + * "us-central1" or "https://mydomain.com". */ @NonNull - public static FirebaseFunctions getInstance(@NonNull String region) { - return getInstance(FirebaseApp.getInstance(), region); + public static FirebaseFunctions getInstance(@NonNull String regionOrCustomDomain) { + return getInstance(FirebaseApp.getInstance(), regionOrCustomDomain); } /** Creates a Cloud Functions client with the default app. */ @@ -202,6 +223,11 @@ URL getURL(String function) { } String str = String.format(urlFormat, region, projectId, function); + + if (customDomain != null && emulatorSettings == null) { + str = customDomain + "/" + function; + } + try { return new URL(str); } catch (MalformedURLException mfe) { diff --git a/firebase-functions/src/main/java/com/google/firebase/functions/FunctionsMultiResourceComponent.java b/firebase-functions/src/main/java/com/google/firebase/functions/FunctionsMultiResourceComponent.java index a017d81f434..6fe3dc8b69d 100644 --- a/firebase-functions/src/main/java/com/google/firebase/functions/FunctionsMultiResourceComponent.java +++ b/firebase-functions/src/main/java/com/google/firebase/functions/FunctionsMultiResourceComponent.java @@ -41,14 +41,15 @@ class FunctionsMultiResourceComponent { this.app = app; } - synchronized FirebaseFunctions get(String region) { - FirebaseFunctions functions = instances.get(region); + synchronized FirebaseFunctions get(String regionOrCustomDomain) { + FirebaseFunctions functions = instances.get(regionOrCustomDomain); String projectId = app.getOptions().getProjectId(); if (functions == null) { functions = - new FirebaseFunctions(app, applicationContext, projectId, region, contextProvider); - instances.put(region, functions); + new FirebaseFunctions( + app, applicationContext, projectId, regionOrCustomDomain, contextProvider); + instances.put(regionOrCustomDomain, functions); } return functions; }