@@ -45,41 +45,37 @@ internal class HttpClient(
4545 override suspend fun post (
4646 url : String ,
4747 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)
5150
5251 override suspend fun get (
5352 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)
5855
5956 override suspend fun put (
6057 url : String ,
6158 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)
6561
6662 override suspend fun patch (
6763 url : String ,
6864 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)
7267
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)
7672
7773 private suspend fun makeRequest (
7874 url : String ,
7975 method : String? ,
8076 jsonBody : JSONObject ? ,
8177 timeout : Int ,
82- cacheKey : String ? ,
78+ headers : OptionalHeaders ? ,
8379 ): HttpResponse {
8480 // If privacy consent is required but not yet given, any non-GET request should be blocked.
8581 if (method != null && _configModelStore .model.consentRequired == true && _configModelStore .model.consentGiven != true ) {
@@ -94,7 +90,7 @@ internal class HttpClient(
9490
9591 try {
9692 return withTimeout(getThreadTimeout(timeout).toLong()) {
97- return @withTimeout makeRequestIODispatcher(url, method, jsonBody, timeout, cacheKey )
93+ return @withTimeout makeRequestIODispatcher(url, method, jsonBody, timeout, headers )
9894 }
9995 } catch (e: TimeoutCancellationException ) {
10096 Logging .error(" HttpClient: Request timed out: $url " , e)
@@ -110,7 +106,7 @@ internal class HttpClient(
110106 method : String? ,
111107 jsonBody : JSONObject ? ,
112108 timeout : Int ,
113- cacheKey : String ? ,
109+ headers : OptionalHeaders ? ,
114110 ): HttpResponse {
115111 var retVal: HttpResponse ? = null
116112
@@ -174,11 +170,16 @@ internal class HttpClient(
174170 outputStream.write(sendBytes)
175171 }
176172
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
179174
175+ if (headers?.cacheKey != null ) {
176+ val eTag =
177+ _prefs .getString(
178+ PreferenceStores .ONESIGNAL ,
179+ PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + headers.cacheKey,
180+ )
180181 if (eTag != null ) {
181- con.setRequestProperty(" if-none-match " , eTag)
182+ con.setRequestProperty(" If-None-Match " , eTag)
182183 Logging .debug(" HttpClient: Adding header if-none-match: $eTag " )
183184 }
184185 }
@@ -187,6 +188,7 @@ internal class HttpClient(
187188 httpResponse = con.responseCode
188189
189190 val retryAfter = retryAfterFromResponse(con)
191+ val retryLimit = retryLimitFromResponse(con)
190192 val newDelayUntil = _time .currentTimeMillis + (retryAfter ? : 0 ) * 1_000
191193 if (newDelayUntil > delayNewRequestsUntil) delayNewRequestsUntil = newDelayUntil
192194
@@ -195,39 +197,44 @@ internal class HttpClient(
195197 val cachedResponse =
196198 _prefs .getString(
197199 PreferenceStores .ONESIGNAL ,
198- PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + cacheKey,
200+ PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + headers?. cacheKey,
199201 )
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+ )
201206
202207 // 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 )
204209 }
205210 HttpURLConnection .HTTP_ACCEPTED , HttpURLConnection .HTTP_CREATED , HttpURLConnection .HTTP_OK -> {
206211 val inputStream = con.inputStream
207212 val scanner = Scanner (inputStream, " UTF-8" )
208213 val json = if (scanner.useDelimiter(" \\ A" ).hasNext()) scanner.next() else " "
209214 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+ )
211218
212- if (cacheKey != null ) {
219+ if (headers?. cacheKey != null ) {
213220 val eTag = con.getHeaderField(" etag" )
214221 if (eTag != null ) {
215222 Logging .debug(" HttpClient: Got Response = Response has etag of $eTag so caching the response." )
216223
217224 _prefs .saveString(
218225 PreferenceStores .ONESIGNAL ,
219- PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + cacheKey,
226+ PreferenceOneSignalKeys .PREFS_OS_ETAG_PREFIX + headers. cacheKey,
220227 eTag,
221228 )
222229 _prefs .saveString(
223230 PreferenceStores .ONESIGNAL ,
224- PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + cacheKey,
231+ PreferenceOneSignalKeys .PREFS_OS_HTTP_CACHE_PREFIX + headers. cacheKey,
225232 json,
226233 )
227234 }
228235 }
229236
230- retVal = HttpResponse (httpResponse, json, retryAfterSeconds = retryAfter)
237+ retVal = HttpResponse (httpResponse, json, retryAfterSeconds = retryAfter, retryLimit = retryLimit )
231238 }
232239 else -> {
233240 Logging .debug(" HttpClient: Got Response = ${method ? : " GET" } ${con.url} - FAILED STATUS: $httpResponse " )
@@ -248,7 +255,7 @@ internal class HttpClient(
248255 Logging .warn(" HttpClient: Got Response = $method - STATUS: $httpResponse - No response body!" )
249256 }
250257
251- retVal = HttpResponse (httpResponse, jsonResponse, retryAfterSeconds = retryAfter)
258+ retVal = HttpResponse (httpResponse, jsonResponse, retryAfterSeconds = retryAfter, retryLimit = retryLimit )
252259 }
253260 }
254261 } catch (t: Throwable ) {
@@ -288,6 +295,19 @@ internal class HttpClient(
288295 }
289296 }
290297
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+
291311 private fun logHTTPSent (
292312 method : String? ,
293313 url : URL ,
0 commit comments