diff --git a/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt new file mode 100644 index 00000000..5fc17035 --- /dev/null +++ b/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/GetStreamUrlTest.kt @@ -0,0 +1,47 @@ +package org.moire.ultrasonic.api.subsonic + +import okhttp3.mockwebserver.MockResponse +import org.amshove.kluent.`should equal to` +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions.V1_6_0 +import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule + +/** + * Integration test for [SubsonicAPIClient.getStreamUrl] method. + */ +class GetStreamUrlTest { + @JvmField @Rule val mockWebServerRule = MockWebServerRule() + + val id = "boom" + private lateinit var client: SubsonicAPIClient + private lateinit var expectedUrl: String + + @Before + fun setUp() { + client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(), + USERNAME, PASSWORD, V1_6_0, CLIENT_ID) + val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString() + expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" + + "&p=${client.passwordHex}&v=${V1_6_0.restApiVersion}&c=$CLIENT_ID&f=json" + } + + @Test + fun `Should return valid stream url`() { + mockWebServerRule.enqueueResponse("ping_ok.json") + + val streamUrl = client.getStreamUrl(id) + + streamUrl `should equal to` expectedUrl + } + + @Test + fun `Should still return stream url if connection failed`() { + mockWebServerRule.mockWebServer.enqueue(MockResponse().setResponseCode(500)) + + val streamUrl = client.getStreamUrl(id) + + streamUrl `should equal to` expectedUrl + } +} diff --git a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt index 988a165b..8e088d9a 100644 --- a/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt +++ b/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIClient.kt @@ -131,6 +131,22 @@ class SubsonicAPIClient(baseUrl: String, } } + /** + * Get stream url. + * + * Calling this method do actual connection to the backend, though not downloading all content. + * + * Consider do not use this method, but [stream] call. + */ + fun getStreamUrl(id: String): String { + val request = api.stream(id).execute() + val url = request.raw().request().url().toString() + if (request.isSuccessful) { + request.body().close() + } + return url + } + private val salt: String by lazy { val secureRandom = SecureRandom() BigInteger(130, secureRandom).toString(32) @@ -145,7 +161,7 @@ class SubsonicAPIClient(baseUrl: String, } } - private val passwordHex: String by lazy { + internal val passwordHex: String by lazy { "enc:${password.toHexBytes()}" }