Skip to content

Commit 40fae11

Browse files
committed
Add custom headers to HttpsCallableOptions
1 parent f5f52fa commit 40fae11

File tree

5 files changed

+85
-38
lines changed

5 files changed

+85
-38
lines changed

firebase-functions/src/androidTest/java/com/google/firebase/functions/CallTests.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,24 @@ class CallTests {
9494
@Test
9595
fun testCustomHeaders() {
9696
val functions = Firebase.functions(app)
97-
val function = functions.getHttpsCallable("headersTest")
97+
98+
val options = HttpsCallableOptions.Builder()
9899
.addHeader("Header1", "value1")
99100
.addHeader("Header2", "value2")
100-
.addHeader("Header1", "value3")
101-
.addHeaders(mapOf("Header3" to "value4"))
101+
.build()
102+
103+
val function = functions.getHttpsCallable("headersTest", options)
104+
.addHeader("Header2", "value3")
105+
.addHeader("Header3", "value4")
106+
.addHeader("Header4", "value5")
107+
.addHeaders(mapOf("Header4" to "value6"))
108+
102109
val actual = Tasks.await(function.call()).getData() as? Map<*, *>
103110

104111
assertThat(actual).isNotNull()
105-
assertThat(actual?.get("Header1")).isEqualTo("value3")
106-
assertThat(actual?.get("Header2")).isEqualTo("value2")
112+
assertThat(actual?.get("Header1")).isEqualTo("value1")
113+
assertThat(actual?.get("Header2")).isEqualTo("value3")
107114
assertThat(actual?.get("Header3")).isEqualTo("value4")
115+
assertThat(actual?.get("Header4")).isEqualTo("value6")
108116
}
109117
}

firebase-functions/src/main/java/com/google/firebase/functions/FirebaseFunctions.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ internal constructor(
176176
name: String,
177177
data: Any?,
178178
options: HttpsCallOptions,
179-
headers: Map<String, String>,
180179
): Task<HttpsCallableResult> {
181180
return providerInstalled.task
182181
.continueWithTask(executor) { contextProvider.getContext(options.limitedUseAppCheckTokens) }
@@ -186,7 +185,7 @@ internal constructor(
186185
}
187186
val context = task.result
188187
val url = getURL(name)
189-
call(url, data, context, options, headers)
188+
call(url, data, context, options)
190189
}
191190
}
192191

@@ -201,7 +200,6 @@ internal constructor(
201200
url: URL,
202201
data: Any?,
203202
options: HttpsCallOptions,
204-
headers: Map<String, String>,
205203
): Task<HttpsCallableResult> {
206204
return providerInstalled.task
207205
.continueWithTask(executor) { contextProvider.getContext(options.limitedUseAppCheckTokens) }
@@ -210,7 +208,7 @@ internal constructor(
210208
return@continueWithTask Tasks.forException<HttpsCallableResult>(task.exception!!)
211209
}
212210
val context = task.result
213-
call(url, data, context, options, headers)
211+
call(url, data, context, options)
214212
}
215213
}
216214

@@ -227,7 +225,6 @@ internal constructor(
227225
data: Any?,
228226
context: HttpsCallableContext?,
229227
options: HttpsCallOptions,
230-
headers: Map<String, String>,
231228
): Task<HttpsCallableResult?> {
232229
Preconditions.checkNotNull(url, "url cannot be null")
233230
val body: MutableMap<String?, Any?> = HashMap()
@@ -237,7 +234,7 @@ internal constructor(
237234
val contentType = MediaType.parse("application/json")
238235
val requestBody = RequestBody.create(contentType, bodyJSON.toString())
239236
// Add custom headers first so that internal headers cannot be overwritten
240-
val customHeaders = Headers.of(headers)
237+
val customHeaders = Headers.of(options.headers)
241238
var request = Request.Builder().url(url).post(requestBody).headers(customHeaders)
242239
if (context!!.authToken != null) {
243240
request = request.header("Authorization", "Bearer " + context.authToken)

firebase-functions/src/main/java/com/google/firebase/functions/HttpsCallOptions.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ internal class HttpsCallOptions {
2222
private var timeout = DEFAULT_TIMEOUT
2323
private var timeoutUnits = DEFAULT_TIMEOUT_UNITS
2424
@JvmField public val limitedUseAppCheckTokens: Boolean
25+
@JvmField val headers: MutableMap<String, String>
2526

2627
/** Creates an (internal) HttpsCallOptions from the (external) [HttpsCallableOptions]. */
2728
internal constructor(publicCallableOptions: HttpsCallableOptions) {
2829
limitedUseAppCheckTokens = publicCallableOptions.limitedUseAppCheckTokens
30+
headers = publicCallableOptions.headers.toMutableMap()
2931
}
3032

3133
internal constructor() {
3234
limitedUseAppCheckTokens = false
35+
headers = mutableMapOf()
3336
}
3437

3538
internal fun getLimitedUseAppCheckTokens(): Boolean {
@@ -56,6 +59,31 @@ internal class HttpsCallOptions {
5659
return timeoutUnits.toMillis(timeout)
5760
}
5861

62+
/**
63+
* Adds an HTTP header for calls from this instance of Functions.
64+
*
65+
* Note that an existing header with the same name will be overwritten.
66+
*
67+
* @param name Name of HTTP header
68+
* @param value Value of HTTP header
69+
*/
70+
internal fun addHeader(name: String, value: String): HttpsCallOptions {
71+
headers[name] = value
72+
return this
73+
}
74+
75+
/**
76+
* Adds all HTTP headers of passed map for calls from this instance of Functions.
77+
*
78+
* Note that an existing header with the same name will be overwritten.
79+
*
80+
* @param headers Map of HTTP headers (name to value)
81+
*/
82+
internal fun addHeaders(headers: Map<String, String>): HttpsCallOptions {
83+
this.headers.putAll(headers)
84+
return this
85+
}
86+
5987
/** Creates a new OkHttpClient with these options applied to it. */
6088
internal fun apply(client: OkHttpClient): OkHttpClient {
6189
return client

firebase-functions/src/main/java/com/google/firebase/functions/HttpsCallableOptions.kt

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,23 @@ private constructor(
2424
* Returns the setting indicating if limited-use App Check tokens are enforced for this function.
2525
*/
2626
// If true, request a limited-use token from AppCheck.
27-
@JvmField public val limitedUseAppCheckTokens: Boolean
27+
@JvmField public val limitedUseAppCheckTokens: Boolean,
28+
@JvmField internal val headers: Map<String, String>,
2829
) {
2930

3031
public fun getLimitedUseAppCheckTokens(): Boolean {
3132
return limitedUseAppCheckTokens
3233
}
3334

35+
public fun getHeaders(): Map<String, String> {
36+
// Returning a defensive copy
37+
return headers.toMap()
38+
}
39+
3440
/** A builder for creating [com.google.firebase.functions.HttpsCallableOptions]. */
3541
public class Builder {
3642
@JvmField public var limitedUseAppCheckTokens: Boolean = false
43+
private val headers: MutableMap<String, String> = mutableMapOf()
3744

3845
/** Returns the setting indicating if limited-use App Check tokens are enforced. */
3946
public fun getLimitedUseAppCheckTokens(): Boolean {
@@ -49,9 +56,34 @@ private constructor(
4956
return this
5057
}
5158

59+
/**
60+
* Adds an HTTP header for callable functions.
61+
*
62+
* Note that an existing header with the same name will be overwritten.
63+
*
64+
* @param name Name of HTTP header
65+
* @param value Value of HTTP header
66+
*/
67+
public fun addHeader(name: String, value: String): Builder {
68+
headers[name] = value
69+
return this
70+
}
71+
72+
/**
73+
* Adds all HTTP headers of passed map for callable functions.
74+
*
75+
* Note that an existing header with the same name will be overwritten.
76+
*
77+
* @param headers Map of HTTP headers (name to value)
78+
*/
79+
public fun addHeaders(headers: Map<String, String>): Builder {
80+
this.headers.putAll(headers)
81+
return this
82+
}
83+
5284
/** Builds a new [com.google.firebase.functions.HttpsCallableOptions]. */
5385
public fun build(): HttpsCallableOptions {
54-
return HttpsCallableOptions(limitedUseAppCheckTokens)
86+
return HttpsCallableOptions(limitedUseAppCheckTokens, headers.toMap())
5587
}
5688
}
5789
}

firebase-functions/src/main/java/com/google/firebase/functions/HttpsCallableReference.kt

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,6 @@ public class HttpsCallableReference {
3434
// Options for how to do the HTTPS call.
3535
@VisibleForTesting internal val options: HttpsCallOptions
3636

37-
private val headers: MutableMap<String, String>
38-
39-
/** Creates a new reference with the given options. */
40-
internal constructor(
41-
functionsClient: FirebaseFunctions,
42-
name: String?,
43-
options: HttpsCallOptions,
44-
headers: MutableMap<String, String>,
45-
) {
46-
this.functionsClient = functionsClient
47-
this.name = name
48-
url = null
49-
this.options = options
50-
this.headers = headers
51-
}
52-
5337
/** Creates a new reference with the given options. */
5438
internal constructor(
5539
functionsClient: FirebaseFunctions,
@@ -60,7 +44,6 @@ public class HttpsCallableReference {
6044
this.name = name
6145
url = null
6246
this.options = options
63-
this.headers = mutableMapOf()
6447
}
6548

6649
/** Creates a new reference with the given options. */
@@ -69,7 +52,6 @@ public class HttpsCallableReference {
6952
name = null
7053
this.url = url
7154
this.options = options
72-
this.headers = mutableMapOf()
7355
}
7456

7557
/**
@@ -115,9 +97,9 @@ public class HttpsCallableReference {
11597
*/
11698
public fun call(data: Any?): Task<HttpsCallableResult> {
11799
return if (name != null) {
118-
functionsClient.call(name, data, options, headers)
100+
functionsClient.call(name, data, options)
119101
} else {
120-
functionsClient.call(url!!, data, options, headers)
102+
functionsClient.call(url!!, data, options)
121103
}
122104
}
123105

@@ -137,9 +119,9 @@ public class HttpsCallableReference {
137119
*/
138120
public fun call(): Task<HttpsCallableResult> {
139121
return if (name != null) {
140-
functionsClient.call(name, null, options, headers)
122+
functionsClient.call(name, null, options)
141123
} else {
142-
functionsClient.call(url!!, null, options, headers)
124+
functionsClient.call(url!!, null, options)
143125
}
144126
}
145127

@@ -168,7 +150,7 @@ public class HttpsCallableReference {
168150
* @param units The units for the specified timeout.
169151
*/
170152
public fun withTimeout(timeout: Long, units: TimeUnit): HttpsCallableReference {
171-
val other = HttpsCallableReference(functionsClient, name, options, headers)
153+
val other = HttpsCallableReference(functionsClient, name, options)
172154
other.setTimeout(timeout, units)
173155
return other
174156
}
@@ -182,7 +164,7 @@ public class HttpsCallableReference {
182164
* @param value Value of HTTP header
183165
*/
184166
public fun addHeader(name: String, value: String): HttpsCallableReference {
185-
headers[name] = value
167+
options.addHeader(name, value)
186168
return this
187169
}
188170

@@ -194,7 +176,7 @@ public class HttpsCallableReference {
194176
* @param headers Map of HTTP headers (name to value)
195177
*/
196178
public fun addHeaders(headers: Map<String, String>): HttpsCallableReference {
197-
this.headers.putAll(headers)
179+
options.addHeaders(headers)
198180
return this
199181
}
200182
}

0 commit comments

Comments
 (0)