Karl
Karl

Reputation: 27

go error handling of 'dial tcp i/o timeout' from docker

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

Answers (1)

Romain
Romain

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

Related Questions