diff --git a/stream-chat-android-client/api/stream-chat-android-client.api b/stream-chat-android-client/api/stream-chat-android-client.api index 9d57059fcaf..dbfa9c1850f 100644 --- a/stream-chat-android-client/api/stream-chat-android-client.api +++ b/stream-chat-android-client/api/stream-chat-android-client.api @@ -219,6 +219,7 @@ public final class io/getstream/chat/android/client/ChatClient$Builder : io/gets public fun (Ljava/lang/String;Landroid/content/Context;)V public final fun baseUrl (Ljava/lang/String;)Lio/getstream/chat/android/client/ChatClient$Builder; public fun build ()Lio/getstream/chat/android/client/ChatClient; + public final fun cdnUrl (Ljava/lang/String;)Lio/getstream/chat/android/client/ChatClient$Builder; public final fun clientDebugger (Lio/getstream/chat/android/client/debugger/ChatClientDebugger;)Lio/getstream/chat/android/client/ChatClient$Builder; public final fun credentialStorage (Lio/getstream/chat/android/client/user/storage/UserCredentialStorage;)Lio/getstream/chat/android/client/ChatClient$Builder; public final fun debugRequests (Z)Lio/getstream/chat/android/client/ChatClient$Builder; diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt index 95cfb10ccde..55805fd1766 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt @@ -96,6 +96,7 @@ import io.getstream.chat.android.client.events.UserUpdatedEvent import io.getstream.chat.android.client.extensions.ATTACHMENT_TYPE_FILE import io.getstream.chat.android.client.extensions.ATTACHMENT_TYPE_IMAGE import io.getstream.chat.android.client.extensions.cidToTypeAndId +import io.getstream.chat.android.client.extensions.extractBaseUrl import io.getstream.chat.android.client.extensions.internal.isLaterThanDays import io.getstream.chat.android.client.header.VersionPrefixHeader import io.getstream.chat.android.client.helpers.AppSettingManager @@ -3582,7 +3583,7 @@ internal constructor( private var forceInsecureConnection = false private var baseUrl: String = "chat.stream-io-api.com" - private var cdnUrl: String = baseUrl + private var cdnUrl: String? = null private var logLevel = ChatLogLevel.NOTHING private var warmUp: Boolean = true private var loggerHandler: ChatLoggerHandler? = null @@ -3737,19 +3738,15 @@ internal constructor( * * @param value The base URL to use. */ - public fun baseUrl(value: String): Builder { - var baseUrl = value - if (baseUrl.startsWith("https://")) { - baseUrl = baseUrl.split("https://").toTypedArray()[1] - } - if (baseUrl.startsWith("http://")) { - baseUrl = baseUrl.split("http://").toTypedArray()[1] - } - if (baseUrl.endsWith("/")) { - baseUrl = baseUrl.substring(0, baseUrl.length - 1) - } - this.baseUrl = baseUrl - return this + public fun baseUrl(value: String): Builder = apply { + baseUrl = value.extractBaseUrl() + } + + /** + * Sets the CDN URL to be used by the client. + */ + public fun cdnUrl(value: String): Builder = apply { + cdnUrl = value.extractBaseUrl() } /** @@ -3847,7 +3844,7 @@ internal constructor( val config = ChatClientConfig( apiKey = apiKey, httpUrl = "$httpProtocol://$baseUrl/", - cdnHttpUrl = "$httpProtocol://$cdnUrl/", + cdnHttpUrl = "$httpProtocol://${cdnUrl ?: baseUrl}/", wssUrl = "$wsProtocol://$baseUrl/", warmUp = warmUp, loggerConfig = ChatLoggerConfigImpl(logLevel, loggerHandler), diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/extensions/StringExtensions.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/extensions/StringExtensions.kt index 0c0529bdd9a..ffdf73af606 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/extensions/StringExtensions.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/extensions/StringExtensions.kt @@ -28,6 +28,7 @@ import io.getstream.log.StreamLog private val snakeRegex = "_[a-zA-Z]".toRegex() private val camelRegex = "(?<=[a-zA-Z])[A-Z]".toRegex() +private val baseUrlRegex = "^(?:https?://)?(.*?)/*$".toRegex() /** * Converts string written in snake case to String in camel case with the first symbol in lower case. @@ -211,3 +212,12 @@ private fun Uri.Builder.appendValueAsQueryParameterIfNotNull(key: String, value: this } } + +/** + * Extracts the base URL from a string. + * For example, "https://domain.lan/" will return "domain.lan". + * + * @return The base URL. + */ +internal fun String.extractBaseUrl(): String = + baseUrlRegex.matchEntire(this)?.groupValues?.get(1) ?: this diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/BaseUrlTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/BaseUrlTest.kt new file mode 100644 index 00000000000..7918165cf02 --- /dev/null +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/extensions/BaseUrlTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2025 Stream.io Inc. All rights reserved. + * + * Licensed under the Stream License; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.getstream.chat.android.client.extensions + +import org.amshove.kluent.`should be equal to` +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource + +internal class BaseUrlTest { + + @ParameterizedTest + @CsvSource( + "domain.lan,domain.lan", + "domain.lan/,domain.lan", + "domain.lan//,domain.lan", + "http://domain.lan,domain.lan", + "http://domain.lan/,domain.lan", + "http://domain.lan//,domain.lan", + "https://domain.lan,domain.lan", + "https://domain.lan/,domain.lan", + "https://domain.lan//,domain.lan", + "10.0.0.10,10.0.0.10", + "10.0.0.10/,10.0.0.10", + "http://10.0.0.10/,10.0.0.10", + "https://10.0.0.10/,10.0.0.10", + ) + fun test(fullUrl: String, baseUrl: String) { + fullUrl.extractBaseUrl() `should be equal to` baseUrl + } +}