summaryrefslogtreecommitdiffstats
path: root/lib/Cepis/Client.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Cepis/Client.pm')
-rw-r--r--lib/Cepis/Client.pm44
1 files changed, 40 insertions, 4 deletions
diff --git a/lib/Cepis/Client.pm b/lib/Cepis/Client.pm
index 35eb51b..e75868b 100644
--- a/lib/Cepis/Client.pm
+++ b/lib/Cepis/Client.pm
@@ -13,9 +13,10 @@ use Time::HiRes ();
use Cepis::Address;
use Cepis::CSV;
use Cepis::Error;
+use Cepis::Faixa;
use Cepis::Health;
-our $VERSION = '0.1.0';
+our $VERSION = '0.2.0';
use constant DEFAULT_URL => 'https://cep.is';
use constant MAX_BATCH => 500;
@@ -120,8 +121,10 @@ sub lookup {
my ( $status, $body ) = $self->_request("/$number");
if ( $status == 404 ) {
- Cepis::Error::CEPNotFound->throw(
- message => "CEP $number does not exist in the DNE database" );
+ my $faixa = _faixa($body);
+ my $message = "CEP $number does not exist in the DNE database";
+ $message .= ' (it would fall in ' . $faixa->label . ')' if $faixa;
+ Cepis::Error::CEPNotFound->throw( message => $message, faixa => $faixa );
}
if ( $status == 400 ) {
Cepis::Error::InvalidCEP->throw(
@@ -394,6 +397,14 @@ sub _error_message {
return "$data->{mensagem}";
}
+sub _faixa {
+ my ($body) = @_;
+
+ my $data = eval { $JSON->decode( defined $body ? $body : '' ) };
+ return undef unless ref $data eq 'HASH';
+ return Cepis::Faixa->from_json( $data->{faixa} );
+}
+
sub _decode {
my ($body) = @_;
return '' unless defined $body;
@@ -575,6 +586,10 @@ A 400 from the API is surfaced as L<Cepis::Error::InvalidCEP> carrying the API's
own message: the format already passed local validation, so the server knows
something this client does not.
+A 404 becomes L<Cepis::Error::CEPNotFound>, and that error may carry a
+L<Cepis::Faixa> in C<< $err->faixa >> naming the municipality the CEP would have
+belonged to — see L</"A not-found that knows where it was">.
+
Throws L<Cepis::Error::InvalidCEP> when the CEP is not 8 digits (no request is
made), L<Cepis::Error::CEPNotFound> when it is well-formed but absent from the
database, L<Cepis::Error::RateLimited> on 429 after every attempt,
@@ -583,6 +598,27 @@ L<Cepis::Error::Network> when the request never completed, and
L<Cepis::Error::InvalidResponse> when a success status carries an unreadable
body.
+=head3 A not-found that knows where it was
+
+ my $address = eval { $client->lookup('25845000') };
+ if ( !$address && ref $@ && $@->isa('Cepis::Error::CEPNotFound') ) {
+ if ( my $faixa = $@->faixa ) {
+ printf "%s does not exist in %s (%d CEPs, %s..%s)\n",
+ '25845000', $faixa->label, $faixa->ceps,
+ $faixa->cep_ini, $faixa->cep_fim;
+ }
+ }
+
+The API's 404 body may carry a C<faixa> block naming the municipality that owns
+the band the CEP fell into. When it does, the error carries a L<Cepis::Faixa>
+and its message names the municipality; when the CEP fell in a band nobody owns,
+the API omits the block and C<< $err->faixa >> is C<undef>.
+
+B<It is still a 404.> Nothing here turns a not-found into an address; the
+lookup threw, and C<faixa> only says where the CEP would have been. Nor is
+C<cep_ini>..C<cep_fim> a list of valid CEPs — the range is sparse, which is what
+C<ceps> is for. L<Cepis::Faixa> spells both out.
+
=head2 lookup_many
my $result = $client->lookup_many( \@ceps );
@@ -643,7 +679,7 @@ C<500>, the most CEPs the API accepts in a single batch request.
=head1 SEE ALSO
-L<Cepis>, L<Cepis::Address>, L<Cepis::Health>, L<Cepis::Error>
+L<Cepis>, L<Cepis::Address>, L<Cepis::Health>, L<Cepis::Error>, L<Cepis::Faixa>
=head1 LICENCE