summaryrefslogtreecommitdiffstats
path: root/src/cepis_errors.f90
diff options
context:
space:
mode:
Diffstat (limited to 'src/cepis_errors.f90')
-rw-r--r--src/cepis_errors.f9083
1 files changed, 83 insertions, 0 deletions
diff --git a/src/cepis_errors.f90 b/src/cepis_errors.f90
new file mode 100644
index 0000000..5a86dec
--- /dev/null
+++ b/src/cepis_errors.f90
@@ -0,0 +1,83 @@
+!> Status codes returned by every fallible procedure in this library.
+!>
+!> Fortran has no exceptions, so every call that can fail takes an
+!> `integer, intent(out) :: status` and a
+!> `character(len=:), allocatable, intent(out) :: message`. `status` is one of
+!> the parameters below; `message` is always allocated, and is the empty string
+!> on success.
+!>
+!> The split is by **the decision the caller has to make**, not by the HTTP
+!> status that caused it. `CEPIS_ERR_INVALID_CEP` and `CEPIS_ERR_NOT_FOUND` are
+!> problems with the request: retrying returns the same answer more slowly. The
+!> three transport errors below them may succeed later, and the client already
+!> retried on its own before returning any of them.
+module cepis_errors
+ implicit none
+ private
+
+ !> The call succeeded.
+ integer, parameter, public :: CEPIS_OK = 0
+
+ !> The CEP is not 8 digits, or the API rejected it with a 400.
+ !>
+ !> Usually returned without any request being made: the client validates
+ !> the format before going to the network.
+ integer, parameter, public :: CEPIS_ERR_INVALID_CEP = 1
+
+ !> The CEP is well-formed but does not exist in the DNE database.
+ integer, parameter, public :: CEPIS_ERR_NOT_FOUND = 2
+
+ !> The API answered 429 on every attempt. `retry_after` carries what the
+ !> server asked for, in seconds, or a negative value when it did not say.
+ integer, parameter, public :: CEPIS_ERR_RATE_LIMITED = 3
+
+ !> The API answered 5xx on every attempt. `http_status` carries the status
+ !> seen on the last attempt.
+ integer, parameter, public :: CEPIS_ERR_SERVER = 4
+
+ !> The request never completed: DNS, refused connection, timeout, TLS.
+ integer, parameter, public :: CEPIS_ERR_NETWORK = 5
+
+ !> A success status came back with a body that cannot be parsed.
+ !>
+ !> In practice something between the caller and the API is answering
+ !> instead of it: a captive Wi-Fi portal, a corporate proxy, an HTML error
+ !> page.
+ integer, parameter, public :: CEPIS_ERR_INVALID_RESPONSE = 6
+
+ !> A configuration value is out of range. Not one of the six categories
+ !> above: it is a programming error, caught before any request is made.
+ integer, parameter, public :: CEPIS_ERR_CONFIG = 7
+
+ public :: cepis_status_name
+
+contains
+
+ !> A short, stable, English name for a status code.
+ pure function cepis_status_name(status) result(name)
+ integer, intent(in) :: status
+ character(len=:), allocatable :: name
+
+ select case (status)
+ case (CEPIS_OK)
+ name = 'ok'
+ case (CEPIS_ERR_INVALID_CEP)
+ name = 'invalid_cep'
+ case (CEPIS_ERR_NOT_FOUND)
+ name = 'not_found'
+ case (CEPIS_ERR_RATE_LIMITED)
+ name = 'rate_limited'
+ case (CEPIS_ERR_SERVER)
+ name = 'server_error'
+ case (CEPIS_ERR_NETWORK)
+ name = 'network_error'
+ case (CEPIS_ERR_INVALID_RESPONSE)
+ name = 'invalid_response'
+ case (CEPIS_ERR_CONFIG)
+ name = 'config_error'
+ case default
+ name = 'unknown'
+ end select
+ end function cepis_status_name
+
+end module cepis_errors