mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 01:39:22 +02:00
Send Content-Length if required
This commit is contained in:
parent
80b58e134d
commit
dac0ce74fe
3 changed files with 78 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2020 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,7 +31,7 @@ val httpClient: OkHttpClient by lazy {
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
builder.addInterceptor (HttpLoggingInterceptor {
|
builder.addInterceptor (HttpLoggingInterceptor {
|
||||||
Log.d("HttpClient", it)
|
Log.d("HttpClient", it)
|
||||||
})
|
}.apply { level = HttpLoggingInterceptor.Level.HEADERS })
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.build()
|
builder.build()
|
||||||
|
|
|
@ -23,12 +23,15 @@ import io.timelimit.android.async.Threads
|
||||||
import io.timelimit.android.coroutines.executeAndWait
|
import io.timelimit.android.coroutines.executeAndWait
|
||||||
import io.timelimit.android.coroutines.waitForResponse
|
import io.timelimit.android.coroutines.waitForResponse
|
||||||
import io.timelimit.android.sync.network.*
|
import io.timelimit.android.sync.network.*
|
||||||
|
import io.timelimit.android.util.okio.LengthSink
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
import okhttp3.internal.closeQuietly
|
||||||
import okio.BufferedSink
|
import okio.BufferedSink
|
||||||
import okio.GzipSink
|
import okio.GzipSink
|
||||||
|
import okio.Sink
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import java.io.OutputStreamWriter
|
import java.io.OutputStreamWriter
|
||||||
|
|
||||||
|
@ -63,24 +66,37 @@ class HttpServerApi(private val endpointWithoutSlashAtEnd: String): ServerApi {
|
||||||
|
|
||||||
private val JSON = "application/json; charset=utf-8".toMediaTypeOrNull()
|
private val JSON = "application/json; charset=utf-8".toMediaTypeOrNull()
|
||||||
|
|
||||||
private fun createJsonRequestBody(serialize: (writer: JsonWriter) -> Unit) = object: RequestBody() {
|
private fun createJsonRequestBody(
|
||||||
override fun contentType() = JSON
|
serialize: (writer: JsonWriter) -> Unit,
|
||||||
override fun writeTo(sink: BufferedSink) {
|
measureContentLength: Boolean
|
||||||
|
): RequestBody {
|
||||||
|
fun write(sink: Sink) {
|
||||||
val writer = JsonWriter(
|
val writer = JsonWriter(
|
||||||
OutputStreamWriter(
|
OutputStreamWriter(
|
||||||
GzipSink(sink)
|
GzipSink(sink)
|
||||||
.buffer().outputStream()
|
.buffer().outputStream()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
serialize(writer)
|
serialize(writer)
|
||||||
|
|
||||||
writer.flush()
|
|
||||||
writer.close()
|
writer.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val length =
|
||||||
|
if (measureContentLength) LengthSink().also { write(it) }.length
|
||||||
|
else null
|
||||||
|
|
||||||
|
return object: RequestBody() {
|
||||||
|
override fun contentType() = JSON
|
||||||
|
override fun writeTo(sink: BufferedSink) = write(sink)
|
||||||
|
override fun contentLength(): Long = length ?: -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var sendContentLength = false
|
||||||
|
|
||||||
override suspend fun getTimeInMillis(): Long {
|
override suspend fun getTimeInMillis(): Long {
|
||||||
httpClient.newCall(
|
httpClient.newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
|
@ -595,10 +611,30 @@ class HttpServerApi(private val endpointWithoutSlashAtEnd: String): ServerApi {
|
||||||
path: String,
|
path: String,
|
||||||
requestBody: (writer: JsonWriter) -> Unit
|
requestBody: (writer: JsonWriter) -> Unit
|
||||||
): Response {
|
): Response {
|
||||||
|
if (!sendContentLength) {
|
||||||
|
val response = postJsonRequest(path, requestBody, transmitContentLength = false)
|
||||||
|
|
||||||
|
if (response.code != 411) return response
|
||||||
|
|
||||||
|
Threads.network.executeAndWait { response.closeQuietly() }
|
||||||
|
|
||||||
|
sendContentLength = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return postJsonRequest(path, requestBody, transmitContentLength = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun postJsonRequest(
|
||||||
|
path: String,
|
||||||
|
requestBody: (writer: JsonWriter) -> Unit,
|
||||||
|
transmitContentLength: Boolean
|
||||||
|
): Response {
|
||||||
|
val body = createJsonRequestBody(requestBody, transmitContentLength)
|
||||||
|
|
||||||
return httpClient.newCall(
|
return httpClient.newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url("$endpointWithoutSlashAtEnd/$path")
|
.url("$endpointWithoutSlashAtEnd/$path")
|
||||||
.post(createJsonRequestBody(requestBody))
|
.post(body)
|
||||||
.header("Content-Encoding", "gzip")
|
.header("Content-Encoding", "gzip")
|
||||||
.build()
|
.build()
|
||||||
).waitForResponse()
|
).waitForResponse()
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package io.timelimit.android.util.okio
|
||||||
|
|
||||||
|
import okio.Buffer
|
||||||
|
import okio.Sink
|
||||||
|
import okio.Timeout
|
||||||
|
|
||||||
|
class LengthSink: Sink {
|
||||||
|
private var lengthInternal = 0L
|
||||||
|
|
||||||
|
val length get() = lengthInternal
|
||||||
|
|
||||||
|
override fun write(source: Buffer, byteCount: Long) { lengthInternal += byteCount }
|
||||||
|
override fun timeout(): Timeout = Timeout.NONE
|
||||||
|
override fun flush() = Unit
|
||||||
|
override fun close() = Unit
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue