fix(kobo): proxy raw request body to kobo store
Some checks failed
Tests / Test server - macos-latest (push) Has been cancelled
Tests / Test server - ubuntu-latest (push) Has been cancelled
Tests / Test server - windows-latest (push) Has been cancelled
Tests / Test webui builds (push) Has been cancelled

Closes: #2289
This commit is contained in:
Gauthier Roebroeck 2026-04-17 10:39:40 +08:00
parent 85edd8b63f
commit 4a7d9a6510
2 changed files with 12 additions and 6 deletions

View file

@ -74,7 +74,7 @@ class KoboProxy(
* raw Kobo sync token returned, and added to the response headers.
*/
fun proxyCurrentRequest(
body: Any? = null,
body: ByteArray? = null,
includeSyncToken: Boolean = false,
): ResponseEntity<JsonNode> {
if (!komgaSettingsProvider.koboProxy) throw IllegalStateException("kobo proxying is disabled")

View file

@ -3,6 +3,7 @@ package org.gotson.komga.interfaces.api.kobo
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.treeToValue
import com.github.benmanes.caffeine.cache.Caffeine
import io.github.oshai.kotlinlogging.KotlinLogging
@ -174,6 +175,7 @@ class KoboController(
private val imageConverter: ImageConverter,
private val mediaRepository: MediaRepository,
private val contentRestrictionChecker: ContentRestrictionChecker,
private val objectMapper: ObjectMapper,
) {
private val cachedKepub =
Caffeine
@ -230,14 +232,16 @@ class KoboController(
*/
@PostMapping("v1/auth/device")
fun authDevice(
@RequestBody body: JsonNode,
@RequestBody rawBody: ByteArray,
): Any {
try {
return koboProxy.proxyCurrentRequest(body)
return koboProxy.proxyCurrentRequest(rawBody)
} catch (_: Exception) {
logger.warn { "Failed to get response from Kobo /v1/auth/device, fallback to noproxy" }
}
val body = objectMapper.readTree(rawBody)
/**
* Komga does not use the /v1/auth/device API call for authentication/authorization.
* Return dummy data to keep the device happy.
@ -546,13 +550,15 @@ class KoboController(
fun updateState(
@AuthenticationPrincipal principal: KomgaPrincipal,
@PathVariable bookId: String,
@RequestBody body: ReadingStateStateUpdateDto,
@RequestBody rawBody: ByteArray,
@RequestHeader(name = X_KOBO_DEVICEID, required = false) koboDeviceId: String = "unknown",
): ResponseEntity<*> {
val body = objectMapper.readValue<ReadingStateStateUpdateDto>(rawBody)
val book =
bookRepository.findByIdOrNull(bookId)
?: if (koboProxy.isEnabled())
return koboProxy.proxyCurrentRequest(body)
return koboProxy.proxyCurrentRequest(rawBody)
else
throw ResponseStatusException(HttpStatus.NOT_FOUND)
@ -733,7 +739,7 @@ class KoboController(
method = [RequestMethod.GET, RequestMethod.PUT, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PATCH],
)
fun catchAll(
@RequestBody body: Any?,
@RequestBody body: ByteArray?,
): ResponseEntity<JsonNode> =
if (koboProxy.isEnabled())
koboProxy.proxyCurrentRequest(body)