diff options
Diffstat (limited to 'src/main/kotlin/org/cepis/Client.kt')
| -rw-r--r-- | src/main/kotlin/org/cepis/Client.kt | 29 |
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, |