Skip to content

Commit 60bc82c

Browse files
committed
avoid setting content length in connections
1 parent 6a21a7d commit 60bc82c

File tree

4 files changed

+83
-80
lines changed

4 files changed

+83
-80
lines changed

src/main/kotlin/com/adamratzman/spotify/SpotifyAPI.kt

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ internal val base = "https://api.spotify.com/v1"
5959
*
6060
*/
6161
abstract class SpotifyAPI internal constructor(
62-
val clientId: String,
63-
val clientSecret: String,
64-
var token: Token,
65-
useCache: Boolean,
66-
var cacheLimit: Int?,
67-
var automaticRefresh: Boolean,
68-
var retryWhenRateLimited: Boolean,
69-
enableLogger: Boolean
62+
val clientId: String,
63+
val clientSecret: String,
64+
var token: Token,
65+
useCache: Boolean,
66+
var cacheLimit: Int?,
67+
var automaticRefresh: Boolean,
68+
var retryWhenRateLimited: Boolean,
69+
enableLogger: Boolean
7070
) {
7171
var useCache = useCache
7272
set(value) {
@@ -158,14 +158,14 @@ abstract class SpotifyAPI internal constructor(
158158
* client authentication
159159
*/
160160
class SpotifyAppAPI internal constructor(
161-
clientId: String,
162-
clientSecret: String,
163-
token: Token,
164-
useCache: Boolean,
165-
cacheLimit: Int?,
166-
automaticRefresh: Boolean,
167-
retryWhenRateLimited: Boolean,
168-
enableLogger: Boolean
161+
clientId: String,
162+
clientSecret: String,
163+
token: Token,
164+
useCache: Boolean,
165+
cacheLimit: Int?,
166+
automaticRefresh: Boolean,
167+
retryWhenRateLimited: Boolean,
168+
enableLogger: Boolean
169169
) : SpotifyAPI(clientId, clientSecret, token, useCache, cacheLimit, automaticRefresh, retryWhenRateLimited, enableLogger) {
170170

171171
override val search: SearchAPI = SearchAPI(this)
@@ -231,15 +231,15 @@ class SpotifyAppAPI internal constructor(
231231
* managed through the scopes exposed in [token]
232232
*/
233233
class SpotifyClientAPI internal constructor(
234-
clientId: String,
235-
clientSecret: String,
236-
token: Token,
237-
automaticRefresh: Boolean,
238-
var redirectUri: String,
239-
useCache: Boolean,
240-
cacheLimit: Int?,
241-
retryWhenRateLimited: Boolean,
242-
enableLogger: Boolean
234+
clientId: String,
235+
clientSecret: String,
236+
token: Token,
237+
automaticRefresh: Boolean,
238+
var redirectUri: String,
239+
useCache: Boolean,
240+
cacheLimit: Int?,
241+
retryWhenRateLimited: Boolean,
242+
enableLogger: Boolean
243243
) : SpotifyAPI(clientId, clientSecret, token, useCache, cacheLimit, automaticRefresh, retryWhenRateLimited, enableLogger) {
244244
override val search: SearchAPI = SearchAPI(this)
245245
override val albums: AlbumAPI = AlbumAPI(this)
@@ -401,5 +401,5 @@ private fun getKlaxon(api: SpotifyAPI) = Klaxon()
401401
.converter(getPublicUserConverter(api))
402402

403403
internal fun executeTokenRequest(httpConnection: HttpConnection, clientId: String, clientSecret: String): HttpResponse {
404-
return httpConnection.execute(HttpHeader("Authorization", "Basic ${"$clientId:$clientSecret".byteEncode()}"))
404+
return httpConnection.execute(listOf(HttpHeader("Authorization", "Basic ${"$clientId:$clientSecret".byteEncode()}")))
405405
}

src/main/kotlin/com/adamratzman/spotify/http/Endpoints.kt

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,19 @@ abstract class SpotifyEndpoint(val api: SpotifyAPI) {
3333
}
3434

3535
internal fun delete(
36-
url: String,
37-
body: String? = null,
38-
contentType: String? = null
36+
url: String,
37+
body: String? = null,
38+
contentType: String? = null
3939
): String {
4040
return execute(url, body, HttpRequestMethod.DELETE, contentType = contentType)
4141
}
4242

4343
private fun execute(
44-
url: String,
45-
body: String? = null,
46-
method: HttpRequestMethod = HttpRequestMethod.GET,
47-
retry202: Boolean = true,
48-
contentType: String? = null
44+
url: String,
45+
body: String? = null,
46+
method: HttpRequestMethod = HttpRequestMethod.GET,
47+
retry202: Boolean = true,
48+
contentType: String? = null
4949
): String {
5050
if (api is SpotifyAppAPI && System.currentTimeMillis() >= api.expireTime) api.refreshToken()
5151

@@ -59,7 +59,7 @@ abstract class SpotifyEndpoint(val api: SpotifyAPI) {
5959

6060
val document = createConnection(url, body, method, contentType).execute(
6161
cacheState?.eTag?.let {
62-
HttpHeader("If-None-Match", it)
62+
listOf(HttpHeader("If-None-Match", it))
6363
}
6464
)
6565

@@ -73,10 +73,10 @@ abstract class SpotifyEndpoint(val api: SpotifyAPI) {
7373
}
7474

7575
private fun handleResponse(
76-
document: HttpResponse,
77-
cacheState: CacheState?,
78-
spotifyRequest: SpotifyRequest,
79-
retry202: Boolean
76+
document: HttpResponse,
77+
cacheState: CacheState?,
78+
spotifyRequest: SpotifyRequest,
79+
retry202: Boolean
8080
): String? {
8181
val statusCode = document.responseCode
8282

@@ -108,16 +108,16 @@ abstract class SpotifyEndpoint(val api: SpotifyAPI) {
108108
}
109109

110110
private fun createConnection(
111-
url: String,
112-
body: String? = null,
113-
method: HttpRequestMethod = HttpRequestMethod.GET,
114-
contentType: String? = null
111+
url: String,
112+
body: String? = null,
113+
method: HttpRequestMethod = HttpRequestMethod.GET,
114+
contentType: String? = null
115115
) = HttpConnection(
116116
url,
117117
method,
118118
body,
119119
contentType,
120-
HttpHeader("Authorization", "Bearer ${api.token.accessToken}"),
120+
listOf(HttpHeader("Authorization", "Bearer ${api.token.accessToken}")),
121121
api = api
122122
)
123123

@@ -184,10 +184,10 @@ class SpotifyCache {
184184
}
185185

186186
data class SpotifyRequest(
187-
val url: String,
188-
val method: HttpRequestMethod,
189-
val body: String?,
190-
val api: SpotifyAPI
187+
val url: String,
188+
val method: HttpRequestMethod,
189+
val body: String?,
190+
val api: SpotifyAPI
191191
)
192192

193193
data class CacheState(val data: String, val eTag: String?, val expireBy: Long = 0) {

src/main/kotlin/com/adamratzman/spotify/http/HttpConnection.kt

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,44 @@ package com.adamratzman.spotify.http
33

44
import com.adamratzman.spotify.SpotifyAPI
55
import com.adamratzman.spotify.models.SpotifyRatelimitedException
6+
import java.io.OutputStreamWriter
67
import java.net.HttpURLConnection
78
import java.net.URL
8-
import java.util.concurrent.Executors
99
import java.util.concurrent.TimeUnit
1010

1111
enum class HttpRequestMethod { GET, POST, PUT, DELETE }
1212
data class HttpHeader(val key: String, val value: String)
1313

1414
internal class HttpConnection(
15-
private val url: String,
16-
private val method: HttpRequestMethod,
17-
private val body: String?,
18-
private val contentType: String?,
19-
private vararg val headers: HttpHeader,
20-
val api: SpotifyAPI? = null
15+
private val url: String,
16+
private val method: HttpRequestMethod,
17+
private val body: String?,
18+
private val contentType: String?,
19+
private val headers: List<HttpHeader> = listOf(),
20+
val api: SpotifyAPI? = null
2121
) {
2222

23-
fun execute(vararg additionalHeaders: HttpHeader?, retryIf502: Boolean = true): HttpResponse {
23+
fun execute(additionalHeaders: List<HttpHeader>? = null, retryIf502: Boolean = true): HttpResponse {
2424
val connection = URL(url).openConnection() as HttpURLConnection
2525
connection.requestMethod = method.toString()
2626

2727
contentType?.let { connection.setRequestProperty("Content-Type", contentType) }
28-
headers.union(additionalHeaders.filterNotNull()).forEach { (key, value) ->
28+
29+
((additionalHeaders ?: listOf()) + headers).forEach { (key, value) ->
2930
connection.setRequestProperty(key, value)
3031
}
3132

32-
if (body != null || method != HttpRequestMethod.GET) {
33+
if (body != null && method != HttpRequestMethod.GET) {
3334
connection.doOutput = true
34-
connection.setFixedLengthStreamingMode(body?.toByteArray()?.size ?: 0)
35-
connection.outputStream.bufferedWriter().use {
36-
body?.also(it::write)
37-
it.close()
35+
// connection.setFixedLengthStreamingMode(body.toByteArray().size)
36+
val os = connection.outputStream
37+
val osw = OutputStreamWriter(os)
38+
osw.write(body)
39+
osw.apply {
40+
flush()
41+
close()
3842
}
43+
os.close()
3944
}
4045

4146
connection.connect()
@@ -44,7 +49,7 @@ internal class HttpConnection(
4449

4550
if (responseCode == 502 && retryIf502) {
4651
api?.logger?.logError(false, "Received 502 (Invalid response) for URL $url and $this\nRetrying..", null)
47-
return execute(*additionalHeaders, retryIf502 = false)
52+
return execute(additionalHeaders, retryIf502 = false)
4853
}
4954

5055
if (responseCode == 502 && !retryIf502) api?.logger?.logWarning("502 retry successful for $this")
@@ -55,9 +60,9 @@ internal class HttpConnection(
5560
api.logger.logError(false, "The request ($url) was ratelimited for $ratelimit seconds at ${System.currentTimeMillis()}", null)
5661

5762
var response: HttpResponse? = null
58-
(api.executor ?: Executors.newSingleThreadScheduledExecutor()).schedule({
63+
api.executor.schedule({
5964
response = try {
60-
execute(*additionalHeaders, retryIf502 = retryIf502)
65+
execute(additionalHeaders, retryIf502 = retryIf502)
6166
} catch (e: Throwable) {
6267
throw e
6368
}
@@ -76,7 +81,7 @@ internal class HttpConnection(
7681
if (responseCode == 401 && body.contains("access token") &&
7782
api != null && api.automaticRefresh) {
7883
api.refreshToken()
79-
return execute(*additionalHeaders)
84+
return execute(additionalHeaders)
8085
}
8186

8287
return HttpResponse(

src/test/kotlin/com/adamratzman/spotify/utilities/HttpConnectionTests.kt

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ package com.adamratzman.spotify.utilities
44
import com.adamratzman.spotify.api
55
import com.adamratzman.spotify.http.HttpConnection
66
import com.adamratzman.spotify.http.HttpRequestMethod
7-
import com.adamratzman.spotify.models.SpotifyRatelimitedException
87
import org.json.JSONObject
98
import org.junit.jupiter.api.Assertions.assertEquals
10-
import org.junit.jupiter.api.assertThrows
119
import org.spekframework.spek2.Spek
1210
import org.spekframework.spek2.style.specification.describe
1311

@@ -136,17 +134,17 @@ class HttpConnectionTests : Spek({
136134
api.retryWhenRateLimited = false
137135
}
138136

139-
it("thrown exception when can't retry") {
140-
api.retryWhenRateLimited = false
141-
api.useCache = false
142-
assertThrows<SpotifyRatelimitedException> {
143-
(1..50000).forEach {
144-
println(it + 1)
145-
println(System.currentTimeMillis())
146-
println(api.tracks.getTrack("5OT3k9lPxI2jkaryRK3Aop").complete()?.name)
147-
}
148-
}
149-
api.useCache = true
150-
}
137+
/* it("thrown exception when can't retry") {
138+
api.retryWhenRateLimited = false
139+
api.useCache = false
140+
assertThrows<SpotifyRatelimitedException> {
141+
(1..50000).forEach {
142+
println(it + 1)
143+
println(System.currentTimeMillis())
144+
println(api.tracks.getTrack("5OT3k9lPxI2jkaryRK3Aop").complete()?.name)
145+
}
146+
}
147+
api.useCache = true
148+
} */
151149
}
152150
})

0 commit comments

Comments
 (0)