diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:42:22 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:42:22 -0300 |
| commit | b6f876f8b0847c223f3310d3e5208d78982a13c1 (patch) | |
| tree | fce85d75a2e491b6514a4ed7c42dca898f944cc5 /README.md | |
| parent | cf5597871327dbff2c7c743672d696e7ff340c42 (diff) | |
| download | pascal-6637db2cb939c538c039b501ba9d827f07545208.tar.gz | |
A CEP that fails is rarely a random number: it is usually someone who knows
the city and guessed the last digits, and the classic guess is the -000 that
957 municipalities never received. The API now answers those 404s with a
faixa block naming the municipality the number would have belonged to, which
is enough to tell the user "no such CEP in Areal" instead of just "not found".
It stays an error. ECepisNotFound carries the block as a TCepisFaixa and owns
it, the same way an address owns its geo, so no shape of the response can turn
a not-found into an address. Parsing is tolerant on purpose: a faixa that is
absent, null, empty or unreadable leaves Faixa nil rather than costing the
caller the clean not-found underneath.
CepIni and CepFim are the first and the last CEP that actually exist in the
municipality - not the bounds the Correios publish, whose start for Areal is
the very CEP that just failed - and the range between them is sparse. That is
what Ceps is for, and why the comments insist the pair is not a list.
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 49 |
1 files changed, 46 insertions, 3 deletions
@@ -62,10 +62,12 @@ exceptions: | `TCepisAddressList` from `LookupMany` | you — and freeing it frees the addresses inside | | `TCepisHealth` from `Health` | you | | `TCepisGeo` on an address | its address | +| `TCepisFaixa` on an `ECepisNotFound` | its exception, when the handler ends | | the client behind `CepisLookup` and friends | the `Cepis` unit, at finalisation | -`TCepisAddressList.Extract` and `TCepisAddress.ExtractGeo` hand ownership over -when you need one item to outlive its container. +`TCepisAddressList.Extract`, `TCepisAddress.ExtractGeo` and +`ECepisNotFound.ExtractFaixa` hand ownership over when you need one item to +outlive its container. ## Usage @@ -218,7 +220,7 @@ have to make**, not by the HTTP status that caused it: | error | when | does retrying help? | | --- | --- | --- | | `ECepisInvalidCEP` | not 8 digits | no | -| `ECepisNotFound` | well-formed, not in the database | no | +| `ECepisNotFound` | well-formed, not in the database; may carry `Faixa` | no | | `ECepisRateLimited` | 429; carries `RetryAfter` | yes, later | | `ECepisServerError` | 5xx; carries `Status` | yes, later | | `ECepisNetworkError` | DNS, connection, timeout, TLS | yes, later | @@ -235,6 +237,47 @@ except end; ``` +### A not-found that says where the CEP would be + +A CEP that fails is rarely a random number: it is usually someone who knows the +city and guessed the last digits, and the classic guess is the `-000` that 957 +municipalities never received. When the API can place the failed number inside +a municipality's band, the 404 says which one, and `ECepisNotFound` carries it +as a `TCepisFaixa`: + +```pascal +try + Address := CepisLookup('25845-000'); +except + on E: ECepisNotFound do + if E.HasFaixa then + WriteLn('No such CEP in ', E.Faixa.Localidade, '/', E.Faixa.UF, + ' — it has ', E.Faixa.Ceps, ' CEPs, from ', + E.Faixa.CepIni, ' to ', E.Faixa.CepFim) + // No such CEP in Areal/RJ — it has 118 CEPs, from 25845001 to 25849899 + else + WriteLn('No such CEP'); +end; +``` + +**It is still a 404.** The faixa is context for an error, not an address: it +names the municipality the number *would* belong to, and the CEP asked for does +not exist. `E.Faixa` is `nil` — and `E.HasFaixa` is `False` — whenever the +number falls in a band no municipality owns; the API omits the field there +rather than sending `null`, and a malformed one is dropped the same way. The +exception owns the faixa and frees it when the handler ends; `E.ExtractFaixa` +takes it over if you need it to outlive the `except` block. + +Two traps in the pair of bounds: + +- **They are not the published range.** `CepIni` and `CepFim` are the smallest + and the largest CEP that *actually exist* in the municipality. The DNE's own + start for Areal is `25845000` — exactly the CEP that just failed — while + `CepIni` is `25845001`. +- **The range is sparse.** Areal's 118 CEPs are scattered over the ~4,900 + numbers between `25845001` and `25849899`. Never treat the pair as a list of + valid CEPs, and never count from it: that is what `Ceps` is for. + `CepisNormalizeCEP` strips the mask and validates the 8 digits on its own, for code that wants to check before it asks: |