Skip to content

Commit 273fd31

Browse files
authored
Add Proxy support with custom request headers and custom authorization name (#1453)
1 parent f383041 commit 273fd31

File tree

4 files changed

+210
-130
lines changed

4 files changed

+210
-130
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
### Enhancements
77
* Support for performing geospatial queries using the new classes: `GeoPoint`, `GeoCircle`, `GeoBox`, and `GeoPolygon`. See `GeoPoint` documentation on how to persist locations. (Issue [#1403](https://github.com/realm/realm-kotlin/pull/1403))
8+
* [Sync] Add support for customizing authorization headers and adding additional custom headers to all Atlas App service requests with `AppConfiguration.Builder.authorizationHeaderName()` and `AppConfiguration.Builder.addCustomRequestHeader(...)`. (Issue [#1453](https://github.com/realm/realm-kotlin/pull/1453))
89

910
### Fixed
1011
* None.

packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/AppConfiguration.kt

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,25 @@ import org.mongodb.kbson.serialization.EJson
5252
public interface AppConfiguration {
5353

5454
public val appId: String
55+
5556
// TODO Consider replacing with URL type, but didn't want to include io.ktor.http.Url as it
5657
// requires ktor as api dependency
5758
public val baseUrl: String
5859
public val encryptionKey: ByteArray?
5960
public val metadataMode: MetadataMode
6061
public val syncRootDirectory: String
6162

63+
/**
64+
* Authorization header name used for Atlas App services requests.
65+
*/
66+
public val authorizationHeaderName: String
67+
68+
/**
69+
* Custom configured headers that will be sent alongside other headers when
70+
* making network requests towards Atlas App services.
71+
*/
72+
public val customRequestHeaders: Map<String, String>
73+
6274
/**
6375
* The name of app. This is only used for debugging.
6476
*
@@ -119,7 +131,7 @@ public interface AppConfiguration {
119131
* @param appId the application id of the App Services Application.
120132
*/
121133
public class Builder(
122-
private val appId: String
134+
private val appId: String,
123135
) {
124136

125137
private var baseUrl: String = DEFAULT_BASE_URL
@@ -131,9 +143,12 @@ public interface AppConfiguration {
131143
private var networkTransport: NetworkTransport? = null
132144
private var appName: String? = null
133145
private var appVersion: String? = null
146+
134147
@OptIn(ExperimentalKBsonSerializerApi::class)
135148
private var ejson: EJson = EJson
136149
private var httpLogObfuscator: HttpLogObfuscator? = LogObfuscatorImpl
150+
private val customRequestHeaders = mutableMapOf<String, String>()
151+
private var authorizationHeaderName: String = DEFAULT_AUTHORIZATION_HEADER_NAME
137152

138153
/**
139154
* Sets the encryption key used to encrypt the user metadata Realm only. Individual
@@ -179,7 +194,10 @@ public interface AppConfiguration {
179194
* @return the Builder instance used.
180195
*/
181196
@Deprecated("Use io.realm.kotlin.log.RealmLog instead.")
182-
public fun log(level: LogLevel = LogLevel.WARN, customLoggers: List<RealmLogger> = emptyList()): Builder =
197+
public fun log(
198+
level: LogLevel = LogLevel.WARN,
199+
customLoggers: List<RealmLogger> = emptyList(),
200+
): Builder =
183201
apply {
184202
this.logLevel = level
185203
this.userLoggers = customLoggers
@@ -268,6 +286,34 @@ public interface AppConfiguration {
268286
this.httpLogObfuscator = httpLogObfuscator
269287
}
270288

289+
/**
290+
* Sets the name of the HTTP header used to send authorization data in when making requests to
291+
* Atlas App Services. The Atlas App or firewall must have been configured to expect a
292+
* custom authorization header.
293+
*
294+
* The default authorization header is named [DEFAULT_AUTHORIZATION_HEADER_NAME].
295+
*
296+
* @param name name of the header.
297+
* @throws IllegalArgumentException if an empty [name] is provided.
298+
*/
299+
public fun authorizationHeaderName(name: String): Builder = apply {
300+
require(name.isNotEmpty()) { "Non-empty 'name' required." }
301+
authorizationHeaderName = name
302+
}
303+
304+
/**
305+
* Update the custom headers that would be appended to every request to an Atlas App Services Application.
306+
*
307+
* @param block lambda with the the custom header map update instructions.
308+
* @throws IllegalArgumentException if an empty header name is provided.
309+
*/
310+
public fun customRequestHeaders(
311+
block: MutableMap<String, String>.() -> Unit,
312+
): Builder = apply {
313+
customRequestHeaders.block()
314+
require(!customRequestHeaders.containsKey("")) { "Non-empty custom header name required." }
315+
}
316+
271317
/**
272318
* Sets the default EJson decoder that would be use to encode and decode arguments and results
273319
* when calling remote Atlas [Functions], authenticating with a [customFunction], and retrieving
@@ -327,22 +373,25 @@ public interface AppConfiguration {
327373
}
328374

329375
val appLogger = ContextLogger("Sdk")
330-
val networkTransport: (dispatcher: DispatcherHolder) -> NetworkTransport = { dispatcherHolder ->
331-
val logger: Logger = object : Logger {
332-
override fun log(message: String) {
333-
val obfuscatedMessage = httpLogObfuscator?.obfuscate(message)
334-
appLogger.debug(obfuscatedMessage ?: message)
376+
val networkTransport: (dispatcher: DispatcherHolder) -> NetworkTransport =
377+
{ dispatcherHolder ->
378+
val logger: Logger = object : Logger {
379+
override fun log(message: String) {
380+
val obfuscatedMessage = httpLogObfuscator?.obfuscate(message)
381+
appLogger.debug(obfuscatedMessage ?: message)
382+
}
335383
}
384+
networkTransport ?: KtorNetworkTransport(
385+
// FIXME Add AppConfiguration.Builder option to set timeout as a Duration with default \
386+
// constant in AppConfiguration.Companion
387+
// https://github.com/realm/realm-kotlin/issues/408
388+
timeoutMs = 60000,
389+
dispatcherHolder = dispatcherHolder,
390+
logger = logger,
391+
customHeaders = customRequestHeaders,
392+
authorizationHeaderName = authorizationHeaderName
393+
)
336394
}
337-
networkTransport ?: KtorNetworkTransport(
338-
// FIXME Add AppConfiguration.Builder option to set timeout as a Duration with default \
339-
// constant in AppConfiguration.Companion
340-
// https://github.com/realm/realm-kotlin/issues/408
341-
timeoutMs = 60000,
342-
dispatcherHolder = dispatcherHolder,
343-
logger = logger
344-
)
345-
}
346395

347396
return AppConfigurationImpl(
348397
appId = appId,
@@ -359,7 +408,9 @@ public interface AppConfiguration {
359408
appVersion = appVersion,
360409
bundleId = bundleId,
361410
ejson = ejson,
362-
httpLogObfuscator = httpLogObfuscator
411+
httpLogObfuscator = httpLogObfuscator,
412+
customRequestHeaders = customRequestHeaders,
413+
authorizationHeaderName = authorizationHeaderName,
363414
)
364415
}
365416
}

packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class)
5353
override val appVersion: String?,
5454
internal val bundleId: String,
5555
override val ejson: EJson,
56-
override val httpLogObfuscator: HttpLogObfuscator?
56+
override val httpLogObfuscator: HttpLogObfuscator?,
57+
override val customRequestHeaders: Map<String, String>,
58+
override val authorizationHeaderName: String,
5759
) : AppConfiguration {
5860

5961
/**

0 commit comments

Comments
 (0)