Make large attachments fail fast
This commit is contained in:
parent
9afdf5e6e7
commit
29a40080db
4 changed files with 53 additions and 25 deletions
|
@ -1,15 +1,10 @@
|
|||
package io.heckel.ntfy.msg
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import io.heckel.ntfy.BuildConfig
|
||||
import io.heckel.ntfy.db.Notification
|
||||
import io.heckel.ntfy.db.User
|
||||
import io.heckel.ntfy.util.Log
|
||||
import io.heckel.ntfy.util.topicUrl
|
||||
import io.heckel.ntfy.util.topicUrlAuth
|
||||
import io.heckel.ntfy.util.topicUrlJson
|
||||
import io.heckel.ntfy.util.topicUrlJsonPoll
|
||||
import io.heckel.ntfy.util.*
|
||||
import okhttp3.*
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.IOException
|
||||
|
@ -24,12 +19,29 @@ class ApiService {
|
|||
.readTimeout(15, TimeUnit.SECONDS)
|
||||
.writeTimeout(15, TimeUnit.SECONDS)
|
||||
.build()
|
||||
private val publishClient = OkHttpClient.Builder()
|
||||
.callTimeout(5, TimeUnit.MINUTES) // Total timeout for entire request
|
||||
.connectTimeout(15, TimeUnit.SECONDS)
|
||||
.readTimeout(15, TimeUnit.SECONDS)
|
||||
.writeTimeout(15, TimeUnit.SECONDS)
|
||||
.build()
|
||||
private val subscriberClient = OkHttpClient.Builder()
|
||||
.readTimeout(77, TimeUnit.SECONDS) // Assuming that keepalive messages are more frequent than this
|
||||
.build()
|
||||
private val parser = NotificationParser()
|
||||
|
||||
fun publish(baseUrl: String, topic: String, user: User?, message: String, title: String, priority: Int, tags: List<String>, delay: String, body: RequestBody? = null, filename: String = "") {
|
||||
fun publish(
|
||||
baseUrl: String,
|
||||
topic: String,
|
||||
user: User? = null,
|
||||
message: String,
|
||||
title: String = "",
|
||||
priority: Int = 3,
|
||||
tags: List<String> = emptyList(),
|
||||
delay: String = "",
|
||||
body: RequestBody? = null,
|
||||
filename: String = ""
|
||||
) {
|
||||
val url = topicUrl(baseUrl, topic)
|
||||
Log.d(TAG, "Publishing to $url")
|
||||
|
||||
|
@ -56,11 +68,14 @@ class ApiService {
|
|||
} else {
|
||||
builder.put(message.toRequestBody())
|
||||
}
|
||||
client.newCall(builder.build()).execute().use { response ->
|
||||
val request = builder.build()
|
||||
Log.d(TAG, request.toString())
|
||||
publishClient.newCall(request).execute().use { response ->
|
||||
if (response.code == 401 || response.code == 403) {
|
||||
throw UnauthorizedException(user)
|
||||
}
|
||||
if (!response.isSuccessful) {
|
||||
} else if (response.code == 413) {
|
||||
throw EntityTooLargeException()
|
||||
} else if (!response.isSuccessful) {
|
||||
throw Exception("Unexpected response ${response.code} when publishing to $url")
|
||||
}
|
||||
Log.d(TAG, "Successfully published to $url")
|
||||
|
@ -149,6 +164,7 @@ class ApiService {
|
|||
}
|
||||
|
||||
class UnauthorizedException(val user: User?) : Exception()
|
||||
class EntityTooLargeException() : Exception()
|
||||
|
||||
companion object {
|
||||
val USER_AGENT = "ntfy/${BuildConfig.VERSION_NAME} (${BuildConfig.FLAVOR}; Android ${Build.VERSION.RELEASE}; SDK ${Build.VERSION.SDK_INT})"
|
||||
|
|
|
@ -177,16 +177,12 @@ class ShareActivity : AppCompatActivity() {
|
|||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val user = repository.getUser(baseUrl)
|
||||
try {
|
||||
val filename = if (fileUri != null) {
|
||||
fileStat(this@ShareActivity, fileUri).filename
|
||||
val (filename, body) = if (fileUri != null) {
|
||||
val stat = fileStat(this@ShareActivity, fileUri)
|
||||
val body = ContentUriRequestBody(applicationContext.contentResolver, fileUri!!, stat.size)
|
||||
Pair(stat.filename, body)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
val body = if (fileUri != null) {
|
||||
val resolver = applicationContext.contentResolver
|
||||
ContentUriRequestBody(resolver, fileUri!!)
|
||||
} else {
|
||||
null
|
||||
Pair("", null)
|
||||
}
|
||||
api.publish(
|
||||
baseUrl = baseUrl,
|
||||
|
@ -198,7 +194,7 @@ class ShareActivity : AppCompatActivity() {
|
|||
tags = emptyList(),
|
||||
delay = "",
|
||||
body = body, // May be null
|
||||
filename = filename // May be empty
|
||||
filename = filename, // May be empty
|
||||
)
|
||||
runOnUiThread {
|
||||
finish()
|
||||
|
@ -207,9 +203,20 @@ class ShareActivity : AppCompatActivity() {
|
|||
.show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val message = if (e is ApiService.UnauthorizedException) {
|
||||
if (e.user != null) {
|
||||
getString(R.string.detail_test_message_error_unauthorized_user, e.user.username)
|
||||
} else {
|
||||
getString(R.string.detail_test_message_error_unauthorized_anon)
|
||||
}
|
||||
} else if (e is ApiService.EntityTooLargeException) {
|
||||
getString(R.string.detail_test_message_error_too_large)
|
||||
} else {
|
||||
getString(R.string.detail_test_message_error, e.message)
|
||||
}
|
||||
runOnUiThread {
|
||||
progress.visibility = View.GONE
|
||||
errorText.text = e.message
|
||||
errorText.text = message
|
||||
errorImage.visibility = View.VISIBLE
|
||||
errorText.visibility = View.VISIBLE
|
||||
}
|
||||
|
|
|
@ -253,15 +253,19 @@ fun isDarkThemeOn(context: Context): Boolean {
|
|||
|
||||
// https://cketti.de/2020/05/23/content-uris-and-okhttp/
|
||||
class ContentUriRequestBody(
|
||||
private val contentResolver: ContentResolver,
|
||||
private val contentUri: Uri
|
||||
private val resolver: ContentResolver,
|
||||
private val uri: Uri,
|
||||
private val size: Long
|
||||
) : RequestBody() {
|
||||
override fun contentLength(): Long {
|
||||
return size
|
||||
}
|
||||
override fun contentType(): MediaType? {
|
||||
val contentType = contentResolver.getType(contentUri)
|
||||
val contentType = resolver.getType(uri)
|
||||
return contentType?.toMediaTypeOrNull()
|
||||
}
|
||||
override fun writeTo(sink: BufferedSink) {
|
||||
val inputStream = contentResolver.openInputStream(contentUri) ?: throw IOException("Couldn't open content URI for reading")
|
||||
val inputStream = resolver.openInputStream(uri) ?: throw IOException("Couldn't open content URI for reading")
|
||||
inputStream.source().use { source ->
|
||||
sink.writeAll(source)
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
<string name="detail_test_message_error">Cannot send message: %1$s</string>
|
||||
<string name="detail_test_message_error_unauthorized_anon">Cannot send message: Anonymous publishing not allowed</string>
|
||||
<string name="detail_test_message_error_unauthorized_user">Cannot send message: User %1$s not authorized</string>
|
||||
<string name="detail_test_message_error_too_large">Cannot send message: Attachment too large</string>
|
||||
<string name="detail_copied_to_clipboard_message">Copied to clipboard</string>
|
||||
<string name="detail_instant_delivery_enabled">Instant delivery enabled</string>
|
||||
<string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
|
||||
|
|
Loading…
Reference in a new issue