@@ -45,41 +45,37 @@ internal class HttpClient(
45
45
override suspend fun post (
46
46
url : String ,
47
47
body : JSONObject ,
48
- ): HttpResponse {
49
- return makeRequest(url, " POST" , body, _configModelStore .model.httpTimeout, null )
50
- }
48
+ headers : OptionalHeaders ? ,
49
+ ): HttpResponse = makeRequest(url, " POST" , body, _configModelStore .model.httpTimeout, headers)
51
50
52
51
override suspend fun get (
53
52
url : String ,
54
- cacheKey : String? ,
55
- ): HttpResponse {
56
- return makeRequest(url, null , null , _configModelStore .model.httpGetTimeout, cacheKey)
57
- }
53
+ headers : OptionalHeaders ? ,
54
+ ): HttpResponse = makeRequest(url, null , null , _configModelStore .model.httpGetTimeout, headers)
58
55
59
56
override suspend fun put (
60
57
url : String ,
61
58
body : JSONObject ,
62
- ): HttpResponse {
63
- return makeRequest(url, " PUT" , body, _configModelStore .model.httpTimeout, null )
64
- }
59
+ headers : OptionalHeaders ? ,
60
+ ): HttpResponse = makeRequest(url, " PUT" , body, _configModelStore .model.httpTimeout, headers)
65
61
66
62
override suspend fun patch (
67
63
url : String ,
68
64
body : JSONObject ,
69
- ): HttpResponse {
70
- return makeRequest(url, " PATCH" , body, _configModelStore .model.httpTimeout, null )
71
- }
65
+ headers : OptionalHeaders ? ,
66
+ ): HttpResponse = makeRequest(url, " PATCH" , body, _configModelStore .model.httpTimeout, headers)
72
67
73
- override suspend fun delete (url : String ): HttpResponse {
74
- return makeRequest(url, " DELETE" , null , _configModelStore .model.httpTimeout, null )
75
- }
68
+ override suspend fun delete (
69
+ url : String ,
70
+ headers : OptionalHeaders ? ,
71
+ ): HttpResponse = makeRequest(url, " DELETE" , null , _configModelStore .model.httpTimeout, headers)
76
72
77
73
private suspend fun makeRequest (
78
74
url : String ,
79
75
method : String? ,
80
76
jsonBody : JSONObject ? ,
81
77
timeout : Int ,
82
- cacheKey : String ? ,
78
+ headers : OptionalHeaders ? ,
83
79
): HttpResponse {
84
80
// If privacy consent is required but not yet given, any non-GET request should be blocked.
85
81
if (method != null && _configModelStore .model.consentRequired == true && _configModelStore .model.consentGiven != true ) {
@@ -94,7 +90,7 @@ internal class HttpClient(
94
90
95
91
try {
96
92
return withTimeout(getThreadTimeout(timeout).toLong()) {
97
- return @withTimeout makeRequestIODispatcher(url, method, jsonBody, timeout, cacheKey )
93
+ return @withTimeout makeRequestIODispatcher(url, method, jsonBody, timeout, headers )
98
94
}
99
95
} catch (e: TimeoutCancellationException ) {
100
96
Logging .error(" HttpClient: Request timed out: $url " , e)
@@ -110,7 +106,7 @@ internal class HttpClient(
110
106
method : String? ,
111
107
jsonBody : JSONObject ? ,
112
108
timeout : Int ,
113
- cacheKey : String ? ,
109
+ headers : OptionalHeaders ? ,
114
110
): HttpResponse {
115
111
var retVal: HttpResponse ? = null
116
112
@@ -174,11 +170,16 @@ internal class HttpClient(
174
170
outputStream.write(sendBytes)
175
171
}
176
172
177
- if (cacheKey != null ) {
178
- val eTag = _prefs .getString(PreferenceStores .ONESIGNAL , PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + cacheKey)
173
+ // H E A D E R S
179
174
175
+ if (headers?.cacheKey != null ) {
176
+ val eTag =
177
+ _prefs .getString(
178
+ PreferenceStores .ONESIGNAL ,
179
+ PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + headers.cacheKey,
180
+ )
180
181
if (eTag != null ) {
181
- con.setRequestProperty(" if-none-match " , eTag)
182
+ con.setRequestProperty(" If-None-Match " , eTag)
182
183
Logging .debug(" HttpClient: Adding header if-none-match: $eTag " )
183
184
}
184
185
}
@@ -187,6 +188,7 @@ internal class HttpClient(
187
188
httpResponse = con.responseCode
188
189
189
190
val retryAfter = retryAfterFromResponse(con)
191
+ val retryLimit = retryLimitFromResponse(con)
190
192
val newDelayUntil = _time .currentTimeMillis + (retryAfter ? : 0 ) * 1_000
191
193
if (newDelayUntil > delayNewRequestsUntil) delayNewRequestsUntil = newDelayUntil
192
194
@@ -195,39 +197,44 @@ internal class HttpClient(
195
197
val cachedResponse =
196
198
_prefs .getString(
197
199
PreferenceStores .ONESIGNAL ,
198
- PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + cacheKey,
200
+ PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + headers?. cacheKey,
199
201
)
200
- Logging .debug(" HttpClient: Got Response = ${method ? : " GET" } ${con.url} - Using Cached response due to 304: " + cachedResponse)
202
+ Logging .debug(
203
+ " HttpClient: Got Response = ${method ? : " GET" } ${con.url} - Using Cached response due to 304: " +
204
+ cachedResponse,
205
+ )
201
206
202
207
// TODO: SHOULD RETURN OK INSTEAD OF NOT_MODIFIED TO MAKE TRANSPARENT?
203
- retVal = HttpResponse (httpResponse, cachedResponse, retryAfterSeconds = retryAfter)
208
+ retVal = HttpResponse (httpResponse, cachedResponse, retryAfterSeconds = retryAfter, retryLimit = retryLimit )
204
209
}
205
210
HttpURLConnection .HTTP_ACCEPTED , HttpURLConnection .HTTP_CREATED , HttpURLConnection .HTTP_OK -> {
206
211
val inputStream = con.inputStream
207
212
val scanner = Scanner (inputStream, " UTF-8" )
208
213
val json = if (scanner.useDelimiter(" \\ A" ).hasNext()) scanner.next() else " "
209
214
scanner.close()
210
- Logging .debug(" HttpClient: Got Response = ${method ? : " GET" } ${con.url} - STATUS: $httpResponse - Body: " + json)
215
+ Logging .debug(
216
+ " HttpClient: Got Response = ${method ? : " GET" } ${con.url} - STATUS: $httpResponse - Body: " + json,
217
+ )
211
218
212
- if (cacheKey != null ) {
219
+ if (headers?. cacheKey != null ) {
213
220
val eTag = con.getHeaderField(" etag" )
214
221
if (eTag != null ) {
215
222
Logging .debug(" HttpClient: Got Response = Response has etag of $eTag so caching the response." )
216
223
217
224
_prefs .saveString(
218
225
PreferenceStores .ONESIGNAL ,
219
- PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + cacheKey,
226
+ PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + headers. cacheKey,
220
227
eTag,
221
228
)
222
229
_prefs .saveString(
223
230
PreferenceStores .ONESIGNAL ,
224
- PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + cacheKey,
231
+ PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + headers. cacheKey,
225
232
json,
226
233
)
227
234
}
228
235
}
229
236
230
- retVal = HttpResponse (httpResponse, json, retryAfterSeconds = retryAfter)
237
+ retVal = HttpResponse (httpResponse, json, retryAfterSeconds = retryAfter, retryLimit = retryLimit )
231
238
}
232
239
else -> {
233
240
Logging .debug(" HttpClient: Got Response = ${method ? : " GET" } ${con.url} - FAILED STATUS: $httpResponse " )
@@ -248,7 +255,7 @@ internal class HttpClient(
248
255
Logging .warn(" HttpClient: Got Response = $method - STATUS: $httpResponse - No response body!" )
249
256
}
250
257
251
- retVal = HttpResponse (httpResponse, jsonResponse, retryAfterSeconds = retryAfter)
258
+ retVal = HttpResponse (httpResponse, jsonResponse, retryAfterSeconds = retryAfter, retryLimit = retryLimit )
252
259
}
253
260
}
254
261
} catch (t: Throwable ) {
@@ -288,6 +295,19 @@ internal class HttpClient(
288
295
}
289
296
}
290
297
298
+ /* *
299
+ * Reads the HTTP Retry-Limit from the response.
300
+ */
301
+ private fun retryLimitFromResponse (con : HttpURLConnection ): Int? {
302
+ val retryLimitStr = con.getHeaderField(" Retry-Limit" )
303
+ return if (retryLimitStr != null ) {
304
+ Logging .debug(" HttpClient: Response Retry-After: $retryLimitStr " )
305
+ retryLimitStr.toIntOrNull()
306
+ } else {
307
+ null
308
+ }
309
+ }
310
+
291
311
private fun logHTTPSent (
292
312
method : String? ,
293
313
url : URL ,
0 commit comments