diff options
Diffstat (limited to 'lib/Cepis/Client.pm')
| -rw-r--r-- | lib/Cepis/Client.pm | 44 |
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 |