diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:25:04 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:53:07 -0300 |
| commit | 82d92ed4291663bae94014b4363064dbb26c6a51 (patch) | |
| tree | 69d91a59c955f1e6ec6fc0007324b5d73b3f0d01 /lib/src/client.dart | |
| parent | 8e719fc715eb7ae9aa1c842e633f15b5c6cd3688 (diff) | |
| download | dart-0.2.0.tar.gz | |
A CEP that fails a lookup 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
block to the 404 naming the municipality that band belongs to, so the
caller can answer "no, but you were looking at Areal/RJ" instead of just
"no".
It stays an error. Faixa hangs off CepNotFoundException, never off Address,
and cepIni/cepFim are the extremes that actually exist in the municipality
rather than the range the Correios publish — echoing back the published
start would return the very CEP that just failed. The interval is sparse,
which is what ceps is for; it is not a list of alternatives.
Parsing is deliberately forgiving: a missing, empty or malformed block is
null. Losing a clean not-found to a parse error over the hint attached to
it would be a bad trade.
Diffstat (limited to 'lib/src/client.dart')
| -rw-r--r-- | lib/src/client.dart | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/lib/src/client.dart b/lib/src/client.dart index 9ddc165..dc0ddb8 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -186,6 +186,10 @@ class Client { /// own message: the format already passed local validation, so the server /// knows something this client does not. /// + /// A 404 may carry a [Faixa] on [CepNotFoundException.faixa], naming the + /// municipality the CEP would have belonged to. It is context for the error, + /// not an address, and it is `null` whenever the API did not send one. + /// /// Throws [InvalidCepException] when the CEP is not 8 digits — no request is /// made; [CepNotFoundException] when it is well-formed but absent from the /// database; [RateLimitedException] on 429 after every attempt; @@ -200,6 +204,7 @@ class Client { throw CepNotFoundException( 'CEP $number does not exist in the DNE database', cep: number, + faixa: _faixa(reply.body), ); } if (reply.status == 400) { @@ -458,6 +463,26 @@ String _errorMessage(String body, String fallback) { return fallback; } +/// Reads the `faixa` block out of a 404 body, or returns `null`. +/// +/// Every failure — a body that is not JSON, no `faixa` key, a `faixa` that is +/// not an object, one that is empty — is the same `null`. The 404 is the +/// answer the caller asked for; it must not be lost to a parse error over the +/// hint hanging off it. +Faixa? _faixa(String body) { + final Object? data; + try { + data = jsonDecode(body); + } on FormatException { + return null; + } + if (data is! Map<String, dynamic>) { + return null; + } + final block = data['faixa']; + return block is Map<String, dynamic> ? Faixa.fromJson(block) : null; +} + Duration? _retryAfter(String? value) { if (value == null) { return null; |