commit c6bb7d4efbe1e915bf62db4a60fc032209085ffb parent 349b65cd518d50c68adefc82778497cafe6eb5f5 Author: Antoine A <> Date: Fri, 5 Sep 2025 15:45:40 +0200 common: improve base URL type Diffstat:
6 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt @@ -138,7 +138,7 @@ class ExchangeDAO(private val db: Database) { bind(req.wtid) bind(subject) bind(req.amount) - bind(req.exchange_base_url.url) + bind(req.exchange_base_url.url.toString()) bind(req.credit_account.canonical) bind(username) bind(timestamp) diff --git a/common/src/main/kotlin/TalerCommon.kt b/common/src/main/kotlin/TalerCommon.kt @@ -82,10 +82,10 @@ data class TalerProtocolTimestamp( @JvmInline @Serializable(with = BaseURL.Serializer::class) -value class BaseURL private constructor(val url: String) { +value class BaseURL private constructor(val url: URL) { companion object { fun parse(raw: String): BaseURL { - val url = URL(raw) + val url = URI(raw).toURL() if (url.protocol !in setOf("http", "https")) { throw badRequest("only 'http' and 'https' are accepted for baseURL got '${url.protocol}'") } else if (url.host.isNullOrBlank()) { @@ -94,23 +94,21 @@ value class BaseURL private constructor(val url: String) { throw badRequest("require no query in baseURL got '${url.query}'") } else if (url.ref != null) { throw badRequest("require no fragments in baseURL got '${url.ref}'") + } else if (!url.path.endsWith('/')) { + throw badRequest("baseURL path must end with / got '${url.path}'") } - val encoded = url.toString() - if (!encoded.endsWith('/')) { - throw badRequest("baseURL must end with / got '${encoded}'") - } - return BaseURL(encoded) + return BaseURL(url) } } - override fun toString(): String = url + override fun toString(): String = url.toString() internal object Serializer : KSerializer<BaseURL> { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BaseURL", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: BaseURL) { - encoder.encodeString(value.url) + encoder.encodeString(value.url.toString()) } override fun deserialize(decoder: Decoder): BaseURL { diff --git a/common/src/test/kotlin/BaseUrlTest.kt b/common/src/test/kotlin/BaseUrlTest.kt @@ -31,7 +31,7 @@ class BaseUrlTest { "https://example.com:3000/path/", )) { val parsed = BaseURL.parse(valid) - assertEquals(parsed.url, valid) + assertEquals(parsed.toString(), valid) } for (invalid in listOf( diff --git a/common/src/test/kotlin/PaytoTest.kt b/common/src/test/kotlin/PaytoTest.kt @@ -24,6 +24,7 @@ import tech.libeufin.common.Payto import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertNull +import java.net.URL class PaytoTest { @Test diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/ExchangeDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/ExchangeDAO.kt @@ -126,7 +126,7 @@ class ExchangeDAO(private val db: Database) { bind(req.wtid) bind(subject) bind(req.amount) - bind(req.exchange_base_url.url) + bind(req.exchange_base_url.toString()) bind(req.credit_account.toString()) bind(endToEndId) bind(timestamp) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt @@ -56,7 +56,7 @@ class PaymentDAO(private val db: Database) { bind(payment.id.msgId) bind(payment.id.acctSvcrRef) bind(wtid) - bind(baseUrl?.url) + bind(baseUrl?.url?.toString()) one { OutgoingRegistrationResult(