summaryrefslogtreecommitdiffstats
path: root/src/main/kotlin/org/cepis/Client.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/org/cepis/Client.kt')
-rw-r--r--src/main/kotlin/org/cepis/Client.kt29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/main/kotlin/org/cepis/Client.kt b/src/main/kotlin/org/cepis/Client.kt
index e315b74..6a054ae 100644
--- a/src/main/kotlin/org/cepis/Client.kt
+++ b/src/main/kotlin/org/cepis/Client.kt
@@ -95,6 +95,10 @@ class Client(
* API's own message: the format already passed local validation, so the
* server knows something this client does not.
*
+ * A 404 may carry a [Faixa] in [CepNotFoundException.faixa] naming the
+ * municipality the CEP would have belonged to. It is still a 404 — the
+ * block is context for the failure, not an address.
+ *
* @throws InvalidCepException the CEP is not 8 digits (no request is made).
* @throws CepNotFoundException well-formed, but not in the database.
* @throws RateLimitedException 429 after every attempt.
@@ -107,7 +111,12 @@ class Client(
val reply = request("/$number")
if (reply.status == 404) {
- throw CepNotFoundException("CEP $number does not exist in the DNE database")
+ val faixa = faixaFrom(reply.body)
+ val where = faixa?.let { " — that number falls in ${it.localidade}/${it.uf}" } ?: ""
+ throw CepNotFoundException(
+ "CEP $number does not exist in the DNE database$where",
+ faixa,
+ )
}
if (reply.status == 400) {
throw InvalidCepException(errorMessage(reply.body, "CEP $number rejected"))
@@ -210,6 +219,24 @@ class Client(
return parsed as Map<String, Any?>
}
+ /**
+ * The `faixa` block of a 404 body, or `null`.
+ *
+ * Swallows everything: a body that is not JSON, is not an object, or has
+ * no usable `faixa`. The lookup has already failed and the caller is going
+ * to get [CepNotFoundException] either way — losing that exception to a
+ * parse error over an optional field would be a bad trade.
+ */
+ private fun faixaFrom(body: ByteArray): Faixa? {
+ val parsed =
+ try {
+ Json.parse(body.toString(StandardCharsets.UTF_8))
+ } catch (e: JsonSyntaxException) {
+ return null
+ }
+ return Faixa.fromJson((parsed as? Map<*, *>)?.get("faixa"))
+ }
+
private fun errorMessage(
body: ByteArray,
fallback: String,