diff options
Diffstat (limited to 'src/client.cpp')
| -rw-r--r-- | src/client.cpp | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/src/client.cpp b/src/client.cpp index ef19da8..84011a3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -170,6 +170,20 @@ std::string message_from_error_body(const std::string& body, const std::string& return fallback; } +/// Reads the `faixa` block a 404 may carry, never failing. +/// +/// A body that is not JSON, or carries no `faixa`, or carries one that cannot +/// be read, all give `std::nullopt`. The 404 is the answer; the hint attached +/// to it is a bonus and must never cost the diagnosis. +std::optional<Faixa> faixa_from_error_body(const std::string& body) { + const std::optional<Json> parsed = Json::parse(body); + if (!parsed) { + return std::nullopt; + } + const Json* block = parsed->find("faixa"); + return block == nullptr ? std::nullopt : Faixa::from_json(*block); +} + std::string preview(const std::string& body) { constexpr std::size_t kLimit = 120; return body.size() <= kLimit ? body : body.substr(0, kLimit) + "..."; @@ -232,7 +246,12 @@ Address Client::lookup(std::string_view cep) const { const Response response = request("/" + number, {200}); if (response.status == 404) { - throw CepNotFound("CEP " + number + " does not exist in the DNE database"); + std::optional<Faixa> faixa = faixa_from_error_body(response.body); + std::string message = "CEP " + number + " does not exist in the DNE database"; + if (faixa) { + message += " (the range it falls in belongs to " + faixa->localidade + "/" + faixa->uf + ")"; + } + throw CepNotFound(message, std::move(faixa)); } if (response.status == 400) { throw InvalidCep(message_from_error_body(response.body, "CEP " + number + " rejected")); |