Skip to content

Commit

Permalink
feat: add address to tryDial errors (#1763)
Browse files Browse the repository at this point in the history
* fix: propagate body stream error to close function (#1743)

* feat: add address in ErrDialTimeout

* feat: add address in any `tryDial` error

* feat: use struct to wrap error with upstream info

* fix: lint

* fix: wrapped Error() method

* docs: add example to ErrDialWithUpstream

* feat: add address in ErrDialTimeout

* feat: add address in any `tryDial` error

* feat: use struct to wrap error with upstream info

* fix: lint

* fix: wrapped Error() method

* docs: add example to ErrDialWithUpstream

* docs: fix example for ErrDialWithUpstream

---------

Co-authored-by: Max Denushev <denushev@tochka.com>
  • Loading branch information
mdenushev and Max Denushev committed May 2, 2024
1 parent 091733b commit 97d4568
Showing 1 changed file with 41 additions and 6 deletions.
47 changes: 41 additions & 6 deletions tcpdialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fasthttp
import (
"context"
"errors"
"fmt"
"net"
"strconv"
"sync"
Expand Down Expand Up @@ -302,7 +303,7 @@ func (d *TCPDialer) dial(addr string, dualStack bool, timeout time.Duration) (ne
if err == nil {
return conn, nil
}
if err == ErrDialTimeout {
if errors.Is(err, ErrDialTimeout) {
return nil, err
}
idx++
Expand All @@ -316,7 +317,7 @@ func (d *TCPDialer) tryDial(
) (net.Conn, error) {
timeout := time.Until(deadline)
if timeout <= 0 {
return nil, ErrDialTimeout
return nil, wrapDialWithUpstream(ErrDialTimeout, addr)
}

if concurrencyCh != nil {
Expand All @@ -332,7 +333,7 @@ func (d *TCPDialer) tryDial(
}
ReleaseTimer(tc)
if isTimeout {
return nil, ErrDialTimeout
return nil, wrapDialWithUpstream(ErrDialTimeout, addr)
}
}
defer func() { <-concurrencyCh }()
Expand All @@ -346,15 +347,49 @@ func (d *TCPDialer) tryDial(
ctx, cancelCtx := context.WithDeadline(context.Background(), deadline)
defer cancelCtx()
conn, err := dialer.DialContext(ctx, network, addr)
if err != nil && ctx.Err() == context.DeadlineExceeded {
return nil, ErrDialTimeout
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
return nil, wrapDialWithUpstream(ErrDialTimeout, addr)
}
return nil, wrapDialWithUpstream(err, addr)
}
return conn, err
return conn, nil
}

// ErrDialTimeout is returned when TCP dialing is timed out.
var ErrDialTimeout = errors.New("dialing to the given TCP address timed out")

// ErrDialWithUpstream wraps dial error with upstream info.
//
// Should use errors.As to get upstream information from error:
//
// hc := fasthttp.HostClient{Addr: "foo.com,bar.com"}
// err := hc.Do(req, res)
//
// var dialErr *fasthttp.ErrDialWithUpstream
// if errors.As(err, &dialErr) {
// upstream = dialErr.Upstream // 34.206.39.153:80
// }
type ErrDialWithUpstream struct {
Upstream string
wrapErr error
}

func (e *ErrDialWithUpstream) Error() string {
return fmt.Sprintf("error when dialing %s: %s", e.Upstream, e.wrapErr.Error())
}

func (e *ErrDialWithUpstream) Unwrap() error {
return e.wrapErr
}

func wrapDialWithUpstream(err error, upstream string) error {
return &ErrDialWithUpstream{
Upstream: upstream,
wrapErr: err,
}
}

// DefaultDialTimeout is timeout used by Dial and DialDualStack
// for establishing TCP connections.
const DefaultDialTimeout = 3 * time.Second
Expand Down

0 comments on commit 97d4568

Please sign in to comment.