diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:33:25 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:33:25 -0300 |
| commit | 58dbe934a90c1eda8e76cd218a413f01a4d9b11d (patch) | |
| tree | deaee88adad3791c8f010db7f7161a95318ed67e /cepis/client.lua | |
| parent | 7fd555fcaf4304cb0dff3e8f5661565c3618299e (diff) | |
| download | lua-58dbe934a90c1eda8e76cd218a413f01a4d9b11d.tar.gz | |
A CEP that fails is rarely a random number: it is someone who knows the
city and guessed the digits, and the classic guess is the -000 that 957
municipalities never received. The API now answers that 404 with an
optional faixa block naming where the CEP would have been, so a caller
can turn "CEP does not exist" into something the user can act on.
It hangs off the error, never off an address: the lookup still failed.
Parsing gives up quietly at every step — no block, a block that is not
an object, one without a municipality to name — because a broken piece
of context must not turn a clean not-found into a parse failure.
cep_ini and cep_fim are the CEPs that exist, not the range the Correios
publish, and the interval between them is sparse; ceps is what keeps the
pair from being read as a list of valid CEPs.
Diffstat (limited to 'cepis/client.lua')
| -rw-r--r-- | cepis/client.lua | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/cepis/client.lua b/cepis/client.lua index 2a8ae2c..d8a42c9 100644 --- a/cepis/client.lua +++ b/cepis/client.lua @@ -24,7 +24,7 @@ local csv = require("cepis.csv") local M = {} --- Library version, as it appears in the default `User-Agent`. -M.VERSION = "0.1.0" +M.VERSION = "0.2.0" --- Where the API lives unless `base_url` says otherwise. M.DEFAULT_URL = "https://cep.is" @@ -191,6 +191,22 @@ local function error_message(body, fallback) return fallback end +--- The `faixa` of a 404 body, when it carries one. +-- +-- Every step is allowed to give up and return `nil`: the body may not be JSON +-- at all (an edge answering instead of the API), may not carry the block (the +-- API omits it, never nulls it, for a CEP in a band no municipality owns), or +-- may carry something unusable. None of that may turn a clean not-found into a +-- parse failure — the answer to the caller is the same 404 either way, only +-- with less context on it. +local function faixa_from(body) + local ok, data = pcall(json.decode, body or "", 1, nil) + if not ok or type(data) ~= "table" then + return nil + end + return models.new_faixa(data.faixa) +end + local function transport(url) if url:lower():find("^https://") then local ok, https = pcall(require, "ssl.https") @@ -430,6 +446,15 @@ end -- the format already passed local validation, so the server knows something -- this client does not. -- +-- A `not_found` may carry `err.faixa`, a `Faixa` naming the municipality the +-- CEP would have belonged to. It is context for the failure and nothing more — +-- the lookup still failed, and it is `nil` whenever the API omits the block: +-- +-- local address, err = client:lookup("25845000") +-- if not address and err.kind == cepis.NOT_FOUND and err.faixa then +-- print("did you mean a CEP in " .. err.faixa:label() .. "?") +-- end +-- -- @tparam string cep masked or unmasked -- @treturn[1] Address -- @treturn[2] nil @@ -448,12 +473,17 @@ function Client:lookup(cep) end if status == 404 then + local faixa = faixa_from(body) + local message = "CEP " .. number .. " does not exist in the DNE database" + if faixa then + message = message .. ", which would place it in " .. faixa:label() + end return nil, - errors.new( - errors.NOT_FOUND, - "CEP " .. number .. " does not exist in the DNE database", - { cep = number, status = 404 } - ) + errors.new(errors.NOT_FOUND, message, { + cep = number, + status = 404, + faixa = faixa, + }) end if status == 400 then return nil, |