Reputation: 27
We have an application hosted in a docker container calling a REST API, and we'd like to identify network timeouts and handle them in a specific way
Right now to detect timeouts we're using the following code snippet:
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
// do something...
}
While this did work in capturing some cases, when I setup an integration test where firewall/security groups was not configured correctly and the host isn't reachable, it resulted in the following error:
Post \"https://notreal.com/endpoint\": dial tcp 10.130.140.150:8443: i/o timeout
In this case it doesn't seem to fall under net.Error, and ideas on how else to identify this?
Edit:
Looks like this is an issue with our own libraries. The error was originally one that implemented net.Error but was swallowed, returning only the string and no longer implementing Timeout() or Temporary().
Upvotes: 1
Views: 3603
Reputation: 21948
You have to implement it by yourself like you can see in this SO answer. However another way to this is to use an external package that will do that for you like retryablehttp
.
resp, err := retryablehttp.Get("/foo")
if err != nil {
panic(err)
}
The returned response object is an *http.Response, the same thing you would usually get from net/http. Had the request failed one or more times, the above call would block and retry with exponential backoff.
If you need to distinguish transient errors from permanent errors (like endpoint that does not exist) you may try something like this (not tested by myself)?
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
// retry
}
if err != nil {
// unrecoverable error
log.Fatal(err)
}
Catching specific net errors can be tedious since there is a bunch of errors AddrError
, DNSError
and so on.
Upvotes: 1