Move api client configuration to separate data class.

Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
Yahor Berdnikau 2018-06-23 22:30:11 +02:00
parent 52b32d0fd6
commit 8dc9534327
7 changed files with 69 additions and 33 deletions

View File

@ -21,8 +21,14 @@ class GetStreamUrlTest {
@Before
fun setUp() {
client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME, PASSWORD, V1_6_0, CLIENT_ID)
val config = SubsonicClientConfiguration(
mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME,
PASSWORD,
V1_6_0,
CLIENT_ID
)
client = SubsonicAPIClient(config)
val baseExpectedUrl = mockWebServerRule.mockWebServer.url("").toString()
expectedUrl = "$baseExpectedUrl/rest/stream.view?id=$id&u=$USERNAME" +
"&c=$CLIENT_ID&f=json&v=${V1_6_0.restApiVersion}&p=enc:${PASSWORD.toHexBytes()}"

View File

@ -10,11 +10,18 @@ import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
abstract class SubsonicAPIClientTest {
@JvmField @Rule val mockWebServerRule = MockWebServerRule()
protected lateinit var config: SubsonicClientConfiguration
protected lateinit var client: SubsonicAPIClient
@Before
fun setUp() {
client = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME, PASSWORD, CLIENT_VERSION, CLIENT_ID)
config = SubsonicClientConfiguration(
mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME,
PASSWORD,
CLIENT_VERSION,
CLIENT_ID
)
client = SubsonicAPIClient(config)
}
}

View File

@ -10,8 +10,9 @@ import org.junit.Test
class SubsonicApiPasswordTest : SubsonicAPIClientTest() {
@Test
fun `Should pass PasswordMD5Interceptor in query params for api version 1 13 0`() {
val clientV12 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME, PASSWORD, SubsonicAPIVersions.V1_14_0, CLIENT_ID)
val clientV12 = SubsonicAPIClient(
config.copy(minimalProtocolVersion = SubsonicAPIVersions.V1_14_0)
)
mockWebServerRule.enqueueResponse("ping_ok.json")
clientV12.api.ping().execute()
@ -25,8 +26,9 @@ class SubsonicApiPasswordTest : SubsonicAPIClientTest() {
@Test
fun `Should pass PasswordHexInterceptor in query params for api version 1 12 0`() {
val clientV11 = SubsonicAPIClient(mockWebServerRule.mockWebServer.url("/").toString(),
USERNAME, PASSWORD, SubsonicAPIVersions.V1_12_0, CLIENT_ID)
val clientV11 = SubsonicAPIClient(
config.copy(minimalProtocolVersion = SubsonicAPIVersions.V1_12_0)
)
mockWebServerRule.enqueueResponse("ping_ok.json")
clientV11.api.ping().execute()

View File

@ -90,7 +90,15 @@ class SubsonicApiSSLTest {
assertResponseSuccessful(response)
}
private fun createSubsonicClient(allowSelfSignedCertificate: Boolean) = SubsonicAPIClient(
"https://$HOST:$PORT/", USERNAME, PASSWORD, CLIENT_VERSION, CLIENT_ID,
allowSelfSignedCertificate = allowSelfSignedCertificate)
private fun createSubsonicClient(allowSelfSignedCertificate: Boolean): SubsonicAPIClient {
val config = SubsonicClientConfiguration(
"https://$HOST:$PORT/",
USERNAME,
PASSWORD,
CLIENT_VERSION,
CLIENT_ID,
allowSelfSignedCertificate = allowSelfSignedCertificate
)
return SubsonicAPIClient(config)
}
}

View File

@ -36,29 +36,23 @@ private const val READ_TIMEOUT = 60_000L
* @author Yahor Berdnikau
*/
class SubsonicAPIClient(
baseUrl: String,
username: String,
password: String,
minimalProtocolVersion: SubsonicAPIVersions,
clientID: String,
allowSelfSignedCertificate: Boolean = false,
enableLdapUserSupport: Boolean = false,
debug: Boolean = false
config: SubsonicClientConfiguration
) {
private val versionInterceptor = VersionInterceptor(minimalProtocolVersion) {
private val versionInterceptor = VersionInterceptor(config.minimalProtocolVersion) {
protocolVersion = it
}
private val proxyPasswordInterceptor = ProxyPasswordInterceptor(
minimalProtocolVersion,
PasswordHexInterceptor(password),
PasswordMD5Interceptor(password),
enableLdapUserSupport)
config.minimalProtocolVersion,
PasswordHexInterceptor(config.password),
PasswordMD5Interceptor(config.password),
config.enableLdapUserSupport
)
/**
* Get currently used protocol version.
*/
var protocolVersion = minimalProtocolVersion
var protocolVersion = config.minimalProtocolVersion
private set(value) {
field = value
proxyPasswordInterceptor.apiVersion = field
@ -67,13 +61,13 @@ class SubsonicAPIClient(
private val okHttpClient = OkHttpClient.Builder()
.readTimeout(READ_TIMEOUT, MILLISECONDS)
.apply { if (allowSelfSignedCertificate) allowSelfSignedCertificates() }
.apply { if (config.allowSelfSignedCertificate) allowSelfSignedCertificates() }
.addInterceptor { chain ->
// Adds default request params
val originalRequest = chain.request()
val newUrl = originalRequest.url().newBuilder()
.addQueryParameter("u", username)
.addQueryParameter("c", clientID)
.addQueryParameter("u", config.username)
.addQueryParameter("c", config.clientID)
.addQueryParameter("f", "json")
.build()
chain.proceed(originalRequest.newBuilder().url(newUrl).build())
@ -81,7 +75,7 @@ class SubsonicAPIClient(
.addInterceptor(versionInterceptor)
.addInterceptor(proxyPasswordInterceptor)
.addInterceptor(RangeHeaderInterceptor())
.apply { if (debug) addLogging() }
.apply { if (config.debug) addLogging() }
.build()
private val jacksonMapper = ObjectMapper()
@ -90,14 +84,15 @@ class SubsonicAPIClient(
.registerModule(KotlinModule())
private val retrofit = Retrofit.Builder()
.baseUrl("$baseUrl/rest/")
.baseUrl("${config.baseUrl}/rest/")
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create(jacksonMapper))
.build()
private val wrappedApi = ApiVersionCheckWrapper(
retrofit.create(SubsonicAPIDefinition::class.java),
minimalProtocolVersion)
config.minimalProtocolVersion
)
val api: SubsonicAPIDefinition get() = wrappedApi

View File

@ -0,0 +1,15 @@
package org.moire.ultrasonic.api.subsonic
/**
* Provides configuration for [SubsonicAPIClient].
*/
data class SubsonicClientConfiguration(
val baseUrl: String,
val username: String,
val password: String,
val minimalProtocolVersion: SubsonicAPIVersions,
val clientID: String,
val allowSelfSignedCertificate: Boolean = false,
val enableLdapUserSupport: Boolean = false,
val debug: Boolean = false
)

View File

@ -7,6 +7,7 @@ import org.koin.dsl.module.applicationContext
import org.moire.ultrasonic.BuildConfig
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
import org.moire.ultrasonic.api.subsonic.SubsonicClientConfiguration
import org.moire.ultrasonic.cache.PermanentFileStorage
import org.moire.ultrasonic.service.CachedMusicService
import org.moire.ultrasonic.service.MusicService
@ -68,7 +69,7 @@ fun musicServiceModule(sp: SharedPreferences) = applicationContext {
password == null
) {
Log.i(LOG_TAG, "Server credentials is not available")
return@bean SubsonicAPIClient(
return@bean SubsonicClientConfiguration(
baseUrl = "http://localhost",
username = "",
password = "",
@ -81,7 +82,7 @@ fun musicServiceModule(sp: SharedPreferences) = applicationContext {
debug = BuildConfig.DEBUG
)
} else {
return@bean SubsonicAPIClient(
return@bean SubsonicClientConfiguration(
baseUrl = serverUrl,
username = username,
password = password,
@ -96,6 +97,8 @@ fun musicServiceModule(sp: SharedPreferences) = applicationContext {
}
}
bean { return@bean SubsonicAPIClient(get()) }
bean<MusicService>(name = ONLINE_MUSIC_SERVICE) {
return@bean CachedMusicService(RESTMusicService(get(), get()))
}