From 18677b6efd74e3db1b766c455c7fc07c231c2f04 Mon Sep 17 00:00:00 2001 From: pandeymangg Date: Tue, 19 May 2026 11:12:14 +0530 Subject: [PATCH 1/2] simple api response --- .../manager/SurveyManagerInstrumentedTest.kt | 9 - .../FormbricksViewModelInstrumentedTest.kt | 2 - .../java/com/formbricks/android/Formbricks.kt | 12 +- .../android/manager/SurveyManager.kt | 20 +- .../android/model/workspace/Segment.kt | 215 +++--------------- .../SegmentFilterResourceDeserializer.kt | 25 -- .../android/model/workspace/Survey.kt | 13 +- .../android/network/FormbricksApiService.kt | 9 +- 8 files changed, 61 insertions(+), 244 deletions(-) delete mode 100644 android/src/main/java/com/formbricks/android/model/workspace/SegmentFilterResourceDeserializer.kt diff --git a/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt b/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt index aed65b3..7df3ab0 100644 --- a/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt +++ b/android/src/androidTest/java/com/formbricks/android/manager/SurveyManagerInstrumentedTest.kt @@ -51,7 +51,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_nullLanguage_returnsDefault() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -80,7 +79,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_emptyLanguage_returnsDefault() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -109,7 +107,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_explicitDefault_returnsDefault() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -138,7 +135,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_matchByCode_returnsCode() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -177,7 +173,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_matchByAlias_returnsCode() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -216,7 +211,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_disabledLanguage_returnsNull() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -255,7 +249,6 @@ class SurveyManagerInstrumentedTest { fun testGetLanguageCode_defaultLanguage_returnsDefault() { val survey = Survey( id = "test", - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -448,7 +441,6 @@ class SurveyManagerInstrumentedTest { ): Survey { return Survey( id = id, - name = "Test Survey", triggers = null, recontactDays = recontactDays, displayLimit = displayLimit, @@ -464,7 +456,6 @@ class SurveyManagerInstrumentedTest { private fun createMockSurvey(recontactDays: Double?): Survey { return Survey( id = "mockSurvey", - name = "Mock Survey", triggers = null, recontactDays = recontactDays, displayLimit = null, diff --git a/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt b/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt index 8944de5..4235a2a 100644 --- a/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt +++ b/android/src/androidTest/java/com/formbricks/android/webview/FormbricksViewModelInstrumentedTest.kt @@ -35,7 +35,6 @@ class FormbricksViewModelInstrumentedTest { val surveyId = "survey1" val survey = Survey( id = surveyId, - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, @@ -309,7 +308,6 @@ class FormbricksViewModelInstrumentedTest { val surveyId = "survey1" val survey = Survey( id = surveyId, - name = "Test Survey", triggers = null, recontactDays = null, displayLimit = null, diff --git a/android/src/main/java/com/formbricks/android/Formbricks.kt b/android/src/main/java/com/formbricks/android/Formbricks.kt index bac728e..1d527b8 100644 --- a/android/src/main/java/com/formbricks/android/Formbricks.kt +++ b/android/src/main/java/com/formbricks/android/Formbricks.kt @@ -69,12 +69,12 @@ object Formbricks { } - // Validate HTTPS URL - if (!config.appUrl.startsWith("https://", ignoreCase = true)) { - val error = RuntimeException("Only HTTPS URLs are allowed for security reasons. HTTP URLs are not permitted. Provided URL: ${config.appUrl}") - Logger.e(error) - return - } + // Validate HTTPS URL — disabled for local testing +// if (!config.appUrl.startsWith("https://", ignoreCase = true)) { +// val error = RuntimeException("Only HTTPS URLs are allowed for security reasons. HTTP URLs are not permitted. Provided URL: ${config.appUrl}") +// Logger.e(error) +// return +// } applicationContext = context diff --git a/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt b/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt index b9cb9bf..fcb7e15 100644 --- a/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt +++ b/android/src/main/java/com/formbricks/android/manager/SurveyManager.kt @@ -7,8 +7,8 @@ import com.formbricks.android.extensions.expiresAt import com.formbricks.android.extensions.guard import com.formbricks.android.logger.Logger import com.formbricks.android.model.workspace.WorkspaceDataHolder -import com.formbricks.android.model.workspace.SegmentFilterResource -import com.formbricks.android.model.workspace.SegmentFilterResourceDeserializer +import com.formbricks.android.model.workspace.Segment +import com.formbricks.android.model.workspace.SegmentDeserializer import com.formbricks.android.model.workspace.Survey import com.formbricks.android.model.error.SDKError import com.formbricks.android.model.user.Display @@ -42,10 +42,7 @@ object SurveyManager { internal var filteredSurveys: MutableList = mutableListOf() val gson = GsonBuilder() - .registerTypeAdapter( - SegmentFilterResource::class.java, - SegmentFilterResourceDeserializer() - ) + .registerTypeAdapter(Segment::class.java, SegmentDeserializer()) .create() private var workspaceDataHolderJson: String? @@ -116,8 +113,10 @@ object SurveyManager { if (UserManager.userId == null) { filteredSurveys = filteredSurveys.filter { survey -> - // Only include surveys that have no segment filters or null segment - survey.segment?.filters?.isEmpty() ?: true + // Only include surveys that have no segment filters or null segment. + // `hasFilters` is decoded directly from the server response, or + // derived from a legacy cached `filters` array (see SegmentDeserializer). + !(survey.segment?.hasFilters ?: false) }.toMutableList() } @@ -193,7 +192,7 @@ object SurveyManager { val languageCode = getLanguageCode(firstSurveyWithActionClass, currentLanguage) if (languageCode == null) { - val error = RuntimeException("Survey “${firstSurveyWithActionClass.name}” is not available in language “$currentLanguage”. Skipping.") + val error = RuntimeException("Survey “${firstSurveyWithActionClass.id}” is not available in language “$currentLanguage”. Skipping.") Logger.e(error) return } @@ -208,8 +207,7 @@ object SurveyManager { isShowingSurvey = true val timeout = firstSurveyWithActionClass.delay ?: 0.0 if (timeout > 0.0) { - val surveyName = firstSurveyWithActionClass.name - Logger.d("Delaying survey \"$surveyName\" by $timeout seconds") + Logger.d("Delaying survey \"${firstSurveyWithActionClass.id}\" by $timeout seconds") } stopDisplayTimer() displayTimer.schedule(object : TimerTask() { diff --git a/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt b/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt index d900040..97127ea 100644 --- a/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt +++ b/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt @@ -1,190 +1,43 @@ package com.formbricks.android.model.workspace -import com.google.gson.annotations.SerializedName -import kotlinx.serialization.* -import kotlinx.serialization.builtins.ListSerializer -import kotlinx.serialization.json.* -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* - -// MARK: - Connector -@Serializable -enum class SegmentConnector { - @SerialName("and") AND, - @SerialName("or") OR -} - -// MARK: - Filter Operators -@Serializable -enum class FilterOperator { - @SerialName("lessThan") LESS_THAN, - @SerialName("lessEqual") LESS_EQUAL, - @SerialName("greaterThan") GREATER_THAN, - @SerialName("greaterEqual") GREATER_EQUAL, - @SerialName("equals") EQUALS, - @SerialName("notEquals") NOT_EQUALS, - @SerialName("contains") CONTAINS, - @SerialName("doesNotContain") DOES_NOT_CONTAIN, - @SerialName("startsWith") STARTS_WITH, - @SerialName("endsWith") ENDS_WITH, - @SerialName("isSet") IS_SET, - @SerialName("isNotSet") IS_NOT_SET, - @SerialName("userIsIn") USER_IS_IN, - @SerialName("userIsNotIn") USER_IS_NOT_IN -} - -// MARK: - Filter Value -@Serializable(with = SegmentFilterValueSerializer::class) -sealed class SegmentFilterValue { - data class StringValue(val value: String) : SegmentFilterValue() - data class NumberValue(val value: Double) : SegmentFilterValue() -} - -object SegmentFilterValueSerializer : KSerializer { - override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("SegmentFilterValue", PrimitiveKind.STRING) - override fun deserialize(decoder: Decoder): SegmentFilterValue { - val jsonInput = decoder as JsonDecoder - val element = jsonInput.decodeJsonElement() - return when (element) { - is JsonPrimitive -> { - element.doubleOrNull?.let { SegmentFilterValue.NumberValue(it) } - ?: SegmentFilterValue.StringValue(element.content) - } - else -> throw SerializationException("Unexpected type for SegmentFilterValue: $element") - } - } - override fun serialize(encoder: Encoder, value: SegmentFilterValue) { - val jsonOutput = encoder as JsonEncoder - val element = when (value) { - is SegmentFilterValue.NumberValue -> JsonPrimitive(value.value) - is SegmentFilterValue.StringValue -> JsonPrimitive(value.value) - } - jsonOutput.encodeJsonElement(element) - } -} - -// MARK: - Filter Root -@Serializable(with = SegmentFilterRootSerializer::class) -sealed class SegmentFilterRoot { - data class Attribute(val contactAttributeKey: String) : SegmentFilterRoot() - data class Person(val personIdentifier: String) : SegmentFilterRoot() - data class Segment(val segmentId: String) : SegmentFilterRoot() - data class Device(val deviceType: String) : SegmentFilterRoot() -} - -object SegmentFilterRootSerializer : KSerializer { - override val descriptor: SerialDescriptor = buildClassSerialDescriptor("SegmentFilterRoot") { - element("type") - } - override fun deserialize(decoder: Decoder): SegmentFilterRoot { - val input = decoder as JsonDecoder - val obj = input.decodeJsonElement().jsonObject - return when (val type = obj["type"]?.jsonPrimitive?.content) { - "attribute" -> SegmentFilterRoot.Attribute(obj["contactAttributeKey"]!!.jsonPrimitive.content) - "person" -> SegmentFilterRoot.Person(obj["personIdentifier"]!!.jsonPrimitive.content) - "segment" -> SegmentFilterRoot.Segment(obj["segmentId"]!!.jsonPrimitive.content) - "device" -> SegmentFilterRoot.Device(obj["deviceType"]!!.jsonPrimitive.content) - else -> throw SerializationException("Unknown root type: $type") - } - } - override fun serialize(encoder: Encoder, value: SegmentFilterRoot) { - val output = encoder as JsonEncoder - val json = buildJsonObject { - when (value) { - is SegmentFilterRoot.Attribute -> { - put("type", JsonPrimitive("attribute")) - put("contactAttributeKey", JsonPrimitive(value.contactAttributeKey)) - } - is SegmentFilterRoot.Person -> { - put("type", JsonPrimitive("person")) - put("personIdentifier", JsonPrimitive(value.personIdentifier)) - } - is SegmentFilterRoot.Segment -> { - put("type", JsonPrimitive("segment")) - put("segmentId", JsonPrimitive(value.segmentId)) - } - is SegmentFilterRoot.Device -> { - put("type", JsonPrimitive("device")) - put("deviceType", JsonPrimitive(value.deviceType)) - } - } - } - output.encodeJsonElement(json) - } -} - -// MARK: - Qualifier -@Serializable -data class SegmentFilterQualifier( - @SerialName("operator") val `operator`: FilterOperator -) - -// MARK: - Primitive Filter +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import kotlinx.serialization.Serializable +import java.lang.reflect.Type + +/** + * Public client API returns the minimal `{ id, hasFilters }` shape — full + * filter logic (titles, descriptions, conditions) is evaluated server-side + * and must not reach the device. + * + * The custom deserializer also accepts legacy cached payloads that still + * carry a `filters` array (written by older SDK versions before the API was + * slimmed down). In that case `hasFilters` is derived from the array length + * so anonymous users continue to be excluded from segment-targeted surveys + * during the cache window after an SDK upgrade. + */ @Serializable -data class SegmentPrimitiveFilter( +data class Segment( val id: String, - val root: SegmentFilterRoot, - val value: SegmentFilterValue, - val qualifier: SegmentFilterQualifier + val hasFilters: Boolean ) -// MARK: - Recursive Resource -@Serializable(with = SegmentFilterResourceSerializer::class) -sealed class SegmentFilterResource { - data class Primitive(val filter: SegmentPrimitiveFilter) : SegmentFilterResource() - data class Group(val filters: List) : SegmentFilterResource() -} - -object SegmentFilterResourceSerializer : KSerializer { - override val descriptor = buildClassSerialDescriptor("SegmentFilterResource") { - // You can declare children here if you like, - // or leave it empty if you're purely passing through. - } - override fun deserialize(decoder: Decoder): SegmentFilterResource { - val input = decoder as JsonDecoder - val element = input.decodeJsonElement() - return if (element is JsonArray) { - val list = element.map { input.json.decodeFromJsonElement(SegmentFilter.serializer(), it) } - SegmentFilterResource.Group(list) - } else { - val prim = input.json.decodeFromJsonElement(SegmentPrimitiveFilter.serializer(), element) - SegmentFilterResource.Primitive(prim) +class SegmentDeserializer : JsonDeserializer { + override fun deserialize( + json: JsonElement, + typeOfT: Type, + context: JsonDeserializationContext + ): Segment { + val obj = json.asJsonObject + val id = obj.get("id").asString + val hasFilters = when { + obj.has("hasFilters") && !obj.get("hasFilters").isJsonNull -> + obj.get("hasFilters").asBoolean + obj.has("filters") && obj.get("filters").isJsonArray -> + obj.get("filters").asJsonArray.size() > 0 + else -> false } - } - override fun serialize(encoder: Encoder, value: SegmentFilterResource) { - val output = encoder as JsonEncoder - val json = when (value) { - is SegmentFilterResource.Primitive -> output.json.encodeToJsonElement(SegmentPrimitiveFilter.serializer(), value.filter) - is SegmentFilterResource.Group -> output.json.encodeToJsonElement(ListSerializer(SegmentFilter.serializer()), value.filters) - } - output.encodeJsonElement(json) + return Segment(id = id, hasFilters = hasFilters) } } - -// MARK: - Filter Node -@Serializable -data class SegmentFilter( - val id: String, - val connector: SegmentConnector? = null, - val resource: SegmentFilterResource -) - -// MARK: - Segment Model -@OptIn(ExperimentalSerializationApi::class) -@Serializable -data class Segment( - val id: String, - val title: String, - val description: String? = null, - @SerialName("isPrivate") val isPrivate: Boolean, - val filters: List, - // Server may send `workspaceId` (new) or `environmentId` (legacy). Field is - // informational only — not read by SDK logic — so keep it optional. - @SerializedName(value = "workspaceId", alternate = ["environmentId"]) - @SerialName("workspaceId") - @JsonNames("environmentId") - val workspaceId: String? = null, - val createdAt: String, - val updatedAt: String, - val surveys: List -) diff --git a/android/src/main/java/com/formbricks/android/model/workspace/SegmentFilterResourceDeserializer.kt b/android/src/main/java/com/formbricks/android/model/workspace/SegmentFilterResourceDeserializer.kt deleted file mode 100644 index e04d705..0000000 --- a/android/src/main/java/com/formbricks/android/model/workspace/SegmentFilterResourceDeserializer.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.formbricks.android.model.workspace - -import com.google.gson.* -import com.google.gson.reflect.TypeToken -import java.lang.reflect.Type - -class SegmentFilterResourceDeserializer : JsonDeserializer { - override fun deserialize( - json: JsonElement, - typeOfT: Type, - context: JsonDeserializationContext - ): SegmentFilterResource { - return if (json.isJsonArray) { - // JSON is an array → treat it as a Group - val listType = object : TypeToken>() {}.type - val filters: List = context.deserialize(json, listType) - SegmentFilterResource.Group(filters) - } else { - // JSON is an object → treat it as a Primitive - val prim: SegmentPrimitiveFilter = - context.deserialize(json, SegmentPrimitiveFilter::class.java) - SegmentFilterResource.Primitive(prim) - } - } -} diff --git a/android/src/main/java/com/formbricks/android/model/workspace/Survey.kt b/android/src/main/java/com/formbricks/android/model/workspace/Survey.kt index 53ebacf..4b42314 100644 --- a/android/src/main/java/com/formbricks/android/model/workspace/Survey.kt +++ b/android/src/main/java/com/formbricks/android/model/workspace/Survey.kt @@ -22,7 +22,9 @@ data class LanguageDetail( @Serializable data class Survey( @SerializedName("id") val id: String, - @SerializedName("name") val name: String, + // `name` intentionally omitted — internal label, not returned by the + // public client API. Cached payloads from older SDK versions may still + // carry it in JSON; Gson silently ignores unknown keys. @SerializedName("triggers") val triggers: List?, @SerializedName("recontactDays") val recontactDays: Double?, @SerializedName("displayLimit") val displayLimit: Double?, @@ -38,9 +40,12 @@ data class Survey( /// Defines the overlay style displayed behind a survey modal. @Serializable enum class SurveyOverlay(val value: String) { - @SerialName("none") NONE("none"), - @SerialName("light") LIGHT("light"), - @SerialName("dark") DARK("dark"); + // `@SerializedName` for Gson, `@SerialName` for kotlinx.serialization — + // wire path is Gson, but kotlinx annotation kept for parity in case the + // codec ever switches. + @SerializedName("none") @SerialName("none") NONE("none"), + @SerializedName("light") @SerialName("light") LIGHT("light"), + @SerializedName("dark") @SerialName("dark") DARK("dark"); } @Serializable diff --git a/android/src/main/java/com/formbricks/android/network/FormbricksApiService.kt b/android/src/main/java/com/formbricks/android/network/FormbricksApiService.kt index 87d6534..8260ee1 100644 --- a/android/src/main/java/com/formbricks/android/network/FormbricksApiService.kt +++ b/android/src/main/java/com/formbricks/android/network/FormbricksApiService.kt @@ -2,8 +2,8 @@ package com.formbricks.android.network import com.formbricks.android.api.error.FormbricksAPIError import com.formbricks.android.logger.Logger -import com.formbricks.android.model.workspace.SegmentFilterResource -import com.formbricks.android.model.workspace.SegmentFilterResourceDeserializer +import com.formbricks.android.model.workspace.Segment +import com.formbricks.android.model.workspace.SegmentDeserializer import com.formbricks.android.model.workspace.WorkspaceDataHolder import com.formbricks.android.model.workspace.WorkspaceResponse import com.formbricks.android.model.user.PostUserBody @@ -17,10 +17,7 @@ open class FormbricksApiService { private var retrofit: Retrofit? = null private val gson: Gson = GsonBuilder() - .registerTypeAdapter( - SegmentFilterResource::class.java, - SegmentFilterResourceDeserializer() - ) + .registerTypeAdapter(Segment::class.java, SegmentDeserializer()) .create() fun initialize(appUrl: String, isLoggingEnabled: Boolean) { From 0a2cc6e123a4e7d9c509aad300a8195b2ba1a0c6 Mon Sep 17 00:00:00 2001 From: pandeymangg Date: Tue, 19 May 2026 11:22:44 +0530 Subject: [PATCH 2/2] feedback fixes --- .../main/java/com/formbricks/android/Formbricks.kt | 12 ++++++------ .../formbricks/android/model/workspace/Segment.kt | 5 ++++- .../android/network/FormbricksRetrofitBuilder.kt | 12 ++++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/android/src/main/java/com/formbricks/android/Formbricks.kt b/android/src/main/java/com/formbricks/android/Formbricks.kt index 1d527b8..bac728e 100644 --- a/android/src/main/java/com/formbricks/android/Formbricks.kt +++ b/android/src/main/java/com/formbricks/android/Formbricks.kt @@ -69,12 +69,12 @@ object Formbricks { } - // Validate HTTPS URL — disabled for local testing -// if (!config.appUrl.startsWith("https://", ignoreCase = true)) { -// val error = RuntimeException("Only HTTPS URLs are allowed for security reasons. HTTP URLs are not permitted. Provided URL: ${config.appUrl}") -// Logger.e(error) -// return -// } + // Validate HTTPS URL + if (!config.appUrl.startsWith("https://", ignoreCase = true)) { + val error = RuntimeException("Only HTTPS URLs are allowed for security reasons. HTTP URLs are not permitted. Provided URL: ${config.appUrl}") + Logger.e(error) + return + } applicationContext = context diff --git a/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt b/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt index 97127ea..d369c74 100644 --- a/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt +++ b/android/src/main/java/com/formbricks/android/model/workspace/Segment.kt @@ -31,12 +31,15 @@ class SegmentDeserializer : JsonDeserializer { ): Segment { val obj = json.asJsonObject val id = obj.get("id").asString + // Fail-closed: ambiguous payload (neither `hasFilters` nor `filters` present) + // is treated as "has filters" so anonymous users are excluded from segment- + // targeted surveys rather than over-shown. val hasFilters = when { obj.has("hasFilters") && !obj.get("hasFilters").isJsonNull -> obj.get("hasFilters").asBoolean obj.has("filters") && obj.get("filters").isJsonArray -> obj.get("filters").asJsonArray.size() > 0 - else -> false + else -> true } return Segment(id = id, hasFilters = hasFilters) } diff --git a/android/src/main/java/com/formbricks/android/network/FormbricksRetrofitBuilder.kt b/android/src/main/java/com/formbricks/android/network/FormbricksRetrofitBuilder.kt index b38a7a1..1e96314 100644 --- a/android/src/main/java/com/formbricks/android/network/FormbricksRetrofitBuilder.kt +++ b/android/src/main/java/com/formbricks/android/network/FormbricksRetrofitBuilder.kt @@ -13,17 +13,17 @@ import java.util.concurrent.TimeUnit class FormbricksRetrofitBuilder(private val baseUrl: String, private val loggingEnabled: Boolean) { fun getBuilder(): Retrofit.Builder? { // Validate base URL is HTTPS -// if (!baseUrl.startsWith("https://", ignoreCase = true)) { -// val error = RuntimeException("Only HTTPS URLs are allowed. HTTP URLs are not permitted for security reasons. Provided URL: $baseUrl") -// Logger.e(error) -// return null -// } + if (!baseUrl.startsWith("https://", ignoreCase = true)) { + val error = RuntimeException("Only HTTPS URLs are allowed. HTTP URLs are not permitted for security reasons. Provided URL: $baseUrl") + Logger.e(error) + return null + } val clientBuilder = OkHttpClient.Builder() .connectTimeout(CONNECT_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) .readTimeout(READ_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) .followSslRedirects(true) -// .addInterceptor(HttpsOnlyInterceptor()) + .addInterceptor(HttpsOnlyInterceptor()) if (loggingEnabled) { val logging = HttpLoggingInterceptor()