From c7d89735079db6ba20ce4dfe05ce2d5125c13e22 Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 01:58:47 +0300 Subject: [PATCH] Do not append the application MapTiler key to a custom map style url When a homeserver publishes a map_style_url in its .well-known file, the app appended its own MapTiler API key to it, producing a URL with two query strings that the tile server rejects. The map then failed to load for every user of that homeserver, with no way for the operator to opt out. MapTilerTileServerStyleUriBuilder.build() now appends ?key= only to the URL it composes itself from the bundled base url and map ids. A non blank customMapStyleUrl is returned verbatim, so the operator's own credentials survive. This matches Element Web and the self-hosted tile server documentation, both of which treat map_style_url as complete. The two existing tests that pinned the old behaviour are updated, and cases are added for a custom URL that already carries a key, one that carries an unrelated query string, and a blank url falling back to the built-in style. Relates to https://github.com/element-hq/element-x-android/issues/7289 --- .../MapTilerTileServerStyleUriBuilder.kt | 17 +++++----- .../MapTilerTileServerStyleUriBuilderTest.kt | 34 +++++++++++++++++-- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt index 054805d1ab..dd9d99fa04 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilder.kt @@ -29,14 +29,15 @@ internal class MapTilerTileServerStyleUriBuilder( customMapStyleUrl: String?, darkMode: Boolean, ): String { - return buildString { - if (customMapStyleUrl.isNullOrBlank()) { - val mapId = if (darkMode) darkMapId else lightMapId - append("$baseUrl/$mapId/style.json") - } else { - append(customMapStyleUrl) - } - append("?key=$apiKey") + return if (customMapStyleUrl.isNullOrBlank()) { + val mapId = if (darkMode) darkMapId else lightMapId + "$baseUrl/$mapId/style.json?key=$apiKey" + } else { + // A custom style url comes from the homeserver .well-known and is expected to be complete: + // it already carries the operator's own credentials, if any. Appending our api key to it + // adds a second query string and breaks the request. + // See https://github.com/element-hq/element-x-android/issues/7289 + customMapStyleUrl } } } diff --git a/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt index 2e07204594..addc71c3b9 100644 --- a/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt +++ b/features/location/api/src/test/kotlin/io/element/android/features/location/api/internal/MapTilerTileServerStyleUriBuilderTest.kt @@ -46,7 +46,7 @@ class MapTilerTileServerStyleUriBuilderTest { customMapStyleUrl = "https://custom.url/style.json", darkMode = false, ) - ).isEqualTo("https://custom.url/style.json?key=anApiKey") + ).isEqualTo("https://custom.url/style.json") } @Test @@ -56,6 +56,36 @@ class MapTilerTileServerStyleUriBuilderTest { customMapStyleUrl = "https://custom.url/style.json", darkMode = true, ) - ).isEqualTo("https://custom.url/style.json?key=anApiKey") + ).isEqualTo("https://custom.url/style.json") + } + + @Test + fun `custom map uri with its own api key is not altered`() { + assertThat( + builder.build( + customMapStyleUrl = "https://api.maptiler.com/maps/streets-v2/style.json?key=anOperatorKey", + darkMode = false, + ) + ).isEqualTo("https://api.maptiler.com/maps/streets-v2/style.json?key=anOperatorKey") + } + + @Test + fun `custom map uri with an existing query is not altered`() { + assertThat( + builder.build( + customMapStyleUrl = "https://self.hosted/style.json?foo=bar", + darkMode = true, + ) + ).isEqualTo("https://self.hosted/style.json?foo=bar") + } + + @Test + fun `blank custom map uri falls back to the built-in style`() { + assertThat( + builder.build( + customMapStyleUrl = " ", + darkMode = false, + ) + ).isEqualTo("https://base.url/aLightMapId/style.json?key=anApiKey") } }