summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:37:09 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:37:09 -0300
commita891657aa43d2aba06a6347dd2f94edd19afd6ba (patch)
treeb6369ed2c8485455f9c1aa707c1cd287cb8e7065 /README.md
parent794f28199a4dde9d18ec711864336c96c58bb422 (diff)
downloadd-7cfbca977f267904ebcac7e10956876df780daf8.tar.gz
Carry the municipality a missing CEP would belong toHEADv0.2.0main
A 404 is rarely a random number: it is usually someone who knows the city and guessed the digits, and the classic guess is the -000 that 957 municipalities never received. The API now attaches a faixa to the not-found body naming the municipality that owns the range, so the caller can say "no such CEP, but that range is Areal/RJ" instead of only "no". It stays an error. Faixa hangs off CepNotFoundException, never off Address, and parsing is deliberately lenient: an absent, malformed or unnamed block yields a null Nullable, so reading the extra context can never cost the caller the answer it already had. cep_ini and cep_fim are the smallest and largest CEP that actually exist there, not the bounds the Correios publish, and the range between them is sparse — hence ceps, so nobody mistakes the pair for a list.
Diffstat (limited to 'README.md')
-rw-r--r--README.md47
1 files changed, 45 insertions, 2 deletions
diff --git a/README.md b/README.md
index 9c76d3d..9ca1fe7 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Or in `dub.json`:
```json
"dependencies": {
- "cepis": "~>0.1.0"
+ "cepis": "~>0.2.0"
}
```
@@ -166,7 +166,7 @@ status that caused it:
| exception | when | does retrying help? |
| --- | --- | --- |
| `InvalidCepException` | not 8 digits | no |
-| `CepNotFoundException` | well-formed, not in the database | no |
+| `CepNotFoundException` | well-formed, not in the database; may carry `faixa` | no |
| `RateLimitedException` | 429; carries `retryAfter` | yes, later |
| `ServerException` | 5xx; carries `status` | yes, later |
| `NetworkException` | DNS, connection, timeout, TLS | yes, later |
@@ -190,6 +190,49 @@ catch (CepisException error)
API is answering instead of it — a captive Wi-Fi portal, a corporate proxy, an
HTML error page. Useful as a diagnosis: the problem is not in your code.
+### When the CEP does not exist
+
+A 404 sometimes knows *where* the CEP would have been. `CepNotFoundException`
+carries it in `faixa`: the municipality that owns the range the number falls
+in.
+
+```d
+try
+ render(lookup("25845-000"));
+catch (CepNotFoundException error)
+{
+ if (error.faixa.isNull)
+ askForAnotherCep();
+ else
+ {
+ auto f = error.faixa.get;
+ writeln("no such CEP — that range is ", f.localidade, "/", f.uf);
+ writeln(f.ceps, " CEPs, from ", f.cep_ini, " to ", f.cep_fim);
+ // 118 CEPs, from 25845001 to 25849899
+ }
+}
+```
+
+It is **context for an error, not an address.** The status is still 404 and the
+CEP still does not exist; `faixa` never becomes an `Address` and must not be
+rendered as if the lookup had worked.
+
+`cep_ini` and `cep_fim` are the smallest and the largest CEP that **actually
+exist** there — not the bounds the Correios publish. The DNE's own start for
+Areal is `25845000`, which is exactly the CEP that just failed.
+
+The range is **sparse**: Areal's 118 CEPs are scattered across the ~4,900
+numbers between `25845001` and `25849899`. That is what `ceps` is for. Never
+present the pair as the list of valid CEPs for the city, and do not walk it
+expecting the numbers in between to resolve.
+
+`faixa` is null whenever the API sent none — and it is **omitted, never null**,
+when the CEP falls in a band no municipality owns.
+
+Why it exists: 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.
+
## Development
Everything runs through `make`, which shells out to `dub`: