Add Range header modifier.

Add interceptor that modifies call "Range" header. It changes header
value to "bytes=value-".
This commit is contained in:
Yahor Berdnikau 2017-11-05 18:44:31 +01:00
parent be75511bb7
commit 72333f245f
4 changed files with 121 additions and 0 deletions

View File

@ -0,0 +1,35 @@
package org.moire.ultrasonic.api.subsonic.interceptors
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import org.junit.Before
import org.junit.Rule
import org.moire.ultrasonic.api.subsonic.rules.MockWebServerRule
/**
* Base class for testing [okhttp3.Interceptor] implementations.
*/
abstract class BaseInterceptorTest {
@Rule @JvmField val mockWebServerRule = MockWebServerRule()
lateinit var client: OkHttpClient
abstract val interceptor: Interceptor
@Before
fun setUp() {
client = OkHttpClient.Builder().addInterceptor(interceptor).build()
}
/**
* Creates [Request] to use with [mockWebServerRule].
*
* @param additionalParams passes [Request.Builder] to add additionally required
* params to the [Request].
*/
fun createRequest(additionalParams: (Request.Builder) -> Unit): Request = Request.Builder()
.url(mockWebServerRule.mockWebServer.url("/"))
.also { additionalParams(it) }
.build()
}

View File

@ -0,0 +1,59 @@
package org.moire.ultrasonic.api.subsonic.interceptors
import okhttp3.Interceptor
import okhttp3.mockwebserver.MockResponse
import org.amshove.kluent.`should contain`
import org.amshove.kluent.`should equal to`
import org.amshove.kluent.`should not contain`
import org.junit.Test
/**
* Unit test for [RangeHeaderInterceptor].
*/
class RangeHeaderInterceptorTest : BaseInterceptorTest() {
override val interceptor: Interceptor
get() = RangeHeaderInterceptor()
@Test
fun `Should update uppercase range header`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse())
val offset = 111
val request = createRequest {
it.addHeader("Range", "$offset")
}
client.newCall(request).execute()
val executedRequest = mockWebServerRule.mockWebServer.takeRequest()
executedRequest.headers.names() `should contain` "Range"
executedRequest.headers["Range"]!! `should equal to` "bytes=$offset-"
}
@Test
fun `Should not add range header if request doens't contain it`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse())
val request = createRequest { }
client.newCall(request).execute()
val executedRequest = mockWebServerRule.mockWebServer.takeRequest()
executedRequest.headers.names() `should not contain` "Range"
executedRequest.headers.names() `should not contain` "range"
}
@Test
fun `Should update lowercase range header`() {
mockWebServerRule.mockWebServer.enqueue(MockResponse())
val offset = 51233
val request = createRequest {
it.addHeader("range", "$offset")
}
client.newCall(request).execute()
val executedRequest = mockWebServerRule.mockWebServer.takeRequest()
executedRequest.headers.names() `should contain` "Range"
executedRequest.headers["Range"]!! `should equal to` "bytes=$offset-"
}
}

View File

@ -8,6 +8,7 @@ import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import org.moire.ultrasonic.api.subsonic.interceptors.RangeHeaderInterceptor
import org.moire.ultrasonic.api.subsonic.response.StreamResponse
import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse
import retrofit2.Response
@ -51,6 +52,7 @@ class SubsonicAPIClient(baseUrl: String,
.build()
chain.proceed(originalRequest.newBuilder().url(newUrl).build())
}
.addInterceptor(RangeHeaderInterceptor())
.also {
if (debug) {
it.addLogging()

View File

@ -0,0 +1,25 @@
package org.moire.ultrasonic.api.subsonic.interceptors
import okhttp3.Interceptor
import okhttp3.Interceptor.Chain
import okhttp3.Response
/**
* Modifies request "Range" header to be according to HTTP standard.
*
* See [range rfc](https://tools.ietf.org/html/rfc7233).
*/
internal class RangeHeaderInterceptor : Interceptor {
override fun intercept(chain: Chain): Response {
val originalRequest = chain.request()
val headers = originalRequest.headers()
return if (headers.names().contains("Range")) {
val offset = "bytes=${headers["Range"]}-"
chain.proceed(originalRequest.newBuilder()
.removeHeader("Range").addHeader("Range", offset)
.build())
} else {
chain.proceed(originalRequest)
}
}
}