fix: enable errorlint in api, client and pkg
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
This commit is contained in:
parent
d6412f468e
commit
b281a3c4fa
@ -15,6 +15,7 @@
|
||||
package rpctypes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
@ -24,19 +25,20 @@ import (
|
||||
func TestConvert(t *testing.T) {
|
||||
e1 := status.Error(codes.InvalidArgument, "etcdserver: key is not provided")
|
||||
e2 := ErrGRPCEmptyKey
|
||||
e3 := ErrEmptyKey
|
||||
var e3 EtcdError
|
||||
errors.As(ErrEmptyKey, &e3)
|
||||
|
||||
if e1.Error() != e2.Error() {
|
||||
t.Fatalf("expected %q == %q", e1.Error(), e2.Error())
|
||||
}
|
||||
if ev1, ok := status.FromError(e1); ok && ev1.Code() != e3.(EtcdError).Code() {
|
||||
t.Fatalf("expected them to be equal, got %v / %v", ev1.Code(), e3.(EtcdError).Code())
|
||||
if ev1, ok := status.FromError(e1); ok && ev1.Code() != e3.Code() {
|
||||
t.Fatalf("expected them to be equal, got %v / %v", ev1.Code(), e3.Code())
|
||||
}
|
||||
|
||||
if e1.Error() == e3.Error() {
|
||||
t.Fatalf("expected %q != %q", e1.Error(), e3.Error())
|
||||
}
|
||||
if ev2, ok := status.FromError(e2); ok && ev2.Code() != e3.(EtcdError).Code() {
|
||||
t.Fatalf("expected them to be equal, got %v / %v", ev2.Code(), e3.(EtcdError).Code())
|
||||
if ev2, ok := status.FromError(e2); ok && ev2.Code() != e3.Code() {
|
||||
t.Fatalf("expected them to be equal, got %v / %v", ev2.Code(), e3.Code())
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -58,13 +59,13 @@ func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
|
||||
func ofdTryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
|
||||
f, err := os.OpenFile(path, flag, perm)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ofdTryLockFile failed to open %q (%v)", path, err)
|
||||
return nil, fmt.Errorf("ofdTryLockFile failed to open %q (%w)", path, err)
|
||||
}
|
||||
|
||||
flock := wrlck
|
||||
if err = syscall.FcntlFlock(f.Fd(), unix.F_OFD_SETLK, &flock); err != nil {
|
||||
f.Close()
|
||||
if err == syscall.EWOULDBLOCK {
|
||||
if errors.Is(err, syscall.EWOULDBLOCK) {
|
||||
err = ErrLocked
|
||||
}
|
||||
return nil, err
|
||||
@ -79,7 +80,7 @@ func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
|
||||
func ofdLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
|
||||
f, err := os.OpenFile(path, flag, perm)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ofdLockFile failed to open %q (%v)", path, err)
|
||||
return nil, fmt.Errorf("ofdLockFile failed to open %q (%w)", path, err)
|
||||
}
|
||||
|
||||
flock := wrlck
|
||||
|
@ -17,6 +17,7 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
@ -25,10 +26,10 @@ func preallocExtend(f *os.File, sizeInBytes int64) error {
|
||||
// use mode = 0 to change size
|
||||
err := syscall.Fallocate(int(f.Fd()), 0, 0, sizeInBytes)
|
||||
if err != nil {
|
||||
errno, ok := err.(syscall.Errno)
|
||||
var errno syscall.Errno
|
||||
// not supported; fallback
|
||||
// fallocate EINTRs frequently in some environments; fallback
|
||||
if ok && (errno == syscall.ENOTSUP || errno == syscall.EINTR) {
|
||||
if errors.As(err, &errno) && (errno == syscall.ENOTSUP || errno == syscall.EINTR) {
|
||||
return preallocExtendTrunc(f, sizeInBytes)
|
||||
}
|
||||
}
|
||||
@ -39,9 +40,9 @@ func preallocFixed(f *os.File, sizeInBytes int64) error {
|
||||
// use mode = 1 to keep size; see FALLOC_FL_KEEP_SIZE
|
||||
err := syscall.Fallocate(int(f.Fd()), 1, 0, sizeInBytes)
|
||||
if err != nil {
|
||||
errno, ok := err.(syscall.Errno)
|
||||
var errno syscall.Errno
|
||||
// treat not supported as nil error
|
||||
if ok && errno == syscall.ENOTSUP {
|
||||
if errors.As(err, &errno) && errno == syscall.ENOTSUP {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ func GetCluster(serviceScheme, service, name, dns string, apurls types.URLs) ([]
|
||||
|
||||
err := updateNodeMap(service, serviceScheme)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error querying DNS SRV records for _%s %s", service, err)
|
||||
return nil, fmt.Errorf("error querying DNS SRV records for _%s %w", service, err)
|
||||
}
|
||||
return stringParts, nil
|
||||
}
|
||||
@ -123,7 +123,7 @@ func GetClient(service, domain string, serviceName string) (*SRVClients, error)
|
||||
errHTTP := updateURLs(GetSRVService(service, serviceName, "http"), "http")
|
||||
|
||||
if errHTTPS != nil && errHTTP != nil {
|
||||
return nil, fmt.Errorf("dns lookup errors: %s and %s", errHTTPS, errHTTP)
|
||||
return nil, fmt.Errorf("dns lookup errors: %w and %w", errHTTPS, errHTTP)
|
||||
}
|
||||
|
||||
endpoints := make([]string, len(urls))
|
||||
|
@ -15,6 +15,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
@ -57,7 +58,8 @@ func TestReadWriteTimeoutDialer(t *testing.T) {
|
||||
t.Fatal("wait timeout")
|
||||
}
|
||||
|
||||
if operr, ok := err.(*net.OpError); !ok || operr.Op != "write" || !operr.Timeout() {
|
||||
var operr *net.OpError
|
||||
if !errors.As(err, &operr) || operr.Op != "write" || !operr.Timeout() {
|
||||
t.Errorf("err = %v, want write i/o timeout error", err)
|
||||
}
|
||||
|
||||
@ -77,7 +79,7 @@ func TestReadWriteTimeoutDialer(t *testing.T) {
|
||||
t.Fatal("wait timeout")
|
||||
}
|
||||
|
||||
if operr, ok := err.(*net.OpError); !ok || operr.Op != "read" || !operr.Timeout() {
|
||||
if !errors.As(err, &operr) || operr.Op != "read" || !operr.Timeout() {
|
||||
t.Errorf("err = %v, want read i/o timeout error", err)
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
@ -82,7 +83,8 @@ func TestWriteReadTimeoutListener(t *testing.T) {
|
||||
t.Fatal("wait timeout")
|
||||
}
|
||||
|
||||
if operr, ok := err.(*net.OpError); !ok || operr.Op != "write" || !operr.Timeout() {
|
||||
var operr *net.OpError
|
||||
if !errors.As(err, &operr) || operr.Op != "write" || !operr.Timeout() {
|
||||
t.Errorf("err = %v, want write i/o timeout error", err)
|
||||
}
|
||||
writerStopCh <- struct{}{}
|
||||
@ -109,7 +111,7 @@ func TestWriteReadTimeoutListener(t *testing.T) {
|
||||
t.Fatal("wait timeout")
|
||||
}
|
||||
|
||||
if operr, ok := err.(*net.OpError); !ok || operr.Op != "read" || !operr.Timeout() {
|
||||
if !errors.As(err, &operr) || operr.Op != "read" || !operr.Timeout() {
|
||||
t.Errorf("err = %v, want read i/o timeout error", err)
|
||||
}
|
||||
readerStopCh <- struct{}{}
|
||||
|
@ -294,7 +294,7 @@ func (c *Client) getToken(ctx context.Context) error {
|
||||
|
||||
resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password)
|
||||
if err != nil {
|
||||
if err == rpctypes.ErrAuthNotEnabled {
|
||||
if errors.Is(err, rpctypes.ErrAuthNotEnabled) {
|
||||
c.authTokenBundle.UpdateAuthToken("")
|
||||
return nil
|
||||
}
|
||||
@ -605,7 +605,8 @@ func ContextError(ctx context.Context, err error) error {
|
||||
return nil
|
||||
}
|
||||
err = rpctypes.Error(err)
|
||||
if _, ok := err.(rpctypes.EtcdError); ok {
|
||||
var serverErr rpctypes.EtcdError
|
||||
if errors.As(err, &serverErr) {
|
||||
return err
|
||||
}
|
||||
if ev, ok := status.FromError(err); ok {
|
||||
@ -627,7 +628,7 @@ func canceledByCaller(stopCtx context.Context, err error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return err == context.Canceled || err == context.DeadlineExceeded
|
||||
return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
|
||||
}
|
||||
|
||||
// IsConnCanceled returns true, if error is from a closed gRPC connection.
|
||||
@ -645,7 +646,7 @@ func IsConnCanceled(err error) bool {
|
||||
}
|
||||
|
||||
// >= gRPC v1.10.x
|
||||
if err == context.Canceled {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -430,8 +430,8 @@ func TestClientRejectOldCluster(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
if err := c.checkVersion(); err != tt.expectedError {
|
||||
t.Errorf("heckVersion err:%v", err)
|
||||
if err := c.checkVersion(); !errors.Is(err, tt.expectedError) {
|
||||
t.Errorf("checkVersion err:%v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package recipe
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -51,7 +52,7 @@ func newUniqueKV(kv v3.KV, prefix string, val string) (*RemoteKV, error) {
|
||||
if err == nil {
|
||||
return &RemoteKV{kv, newKey, rev, val}, nil
|
||||
}
|
||||
if err != ErrKeyExists {
|
||||
if !errors.Is(err, ErrKeyExists) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -155,7 +156,7 @@ func newUniqueEphemeralKV(s *concurrency.Session, prefix, val string) (ek *Ephem
|
||||
for {
|
||||
newKey := fmt.Sprintf("%s/%v", prefix, time.Now().UnixNano())
|
||||
ek, err = newEphemeralKV(s, newKey, val)
|
||||
if err == nil || err != ErrKeyExists {
|
||||
if err == nil || !errors.Is(err, ErrKeyExists) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -464,7 +465,7 @@ func (l *lessor) recvKeepAliveLoop() (gerr error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if ContextError(l.stopCtx, err) == rpctypes.ErrNoLeader {
|
||||
if errors.Is(ContextError(l.stopCtx, err), rpctypes.ErrNoLeader) {
|
||||
l.closeRequireLeader()
|
||||
}
|
||||
break
|
||||
|
@ -16,6 +16,7 @@ package leasing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -282,7 +283,8 @@ func (lkv *leasingKV) acquire(ctx context.Context, key string, op v3.Op) (*v3.Tx
|
||||
return resp, nil
|
||||
}
|
||||
// retry if transient error
|
||||
if _, ok := err.(rpctypes.EtcdError); ok {
|
||||
var serverErr rpctypes.EtcdError
|
||||
if errors.As(err, &serverErr) {
|
||||
return nil, err
|
||||
}
|
||||
if ev, ok := status.FromError(err); ok && ev.Code() != codes.Unavailable {
|
||||
|
@ -117,7 +117,7 @@ func NewMaintenance(c *Client) Maintenance {
|
||||
dial: func(endpoint string) (pb.MaintenanceClient, func(), error) {
|
||||
conn, err := c.Dial(endpoint)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to dial endpoint %s with maintenance client: %v", endpoint, err)
|
||||
return nil, nil, fmt.Errorf("failed to dial endpoint %s with maintenance client: %w", endpoint, err)
|
||||
}
|
||||
|
||||
cancel := func() { conn.Close() }
|
||||
@ -297,8 +297,8 @@ func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) {
|
||||
}
|
||||
|
||||
func (m *maintenance) logAndCloseWithError(err error, pw *io.PipeWriter) {
|
||||
switch err {
|
||||
case io.EOF:
|
||||
switch {
|
||||
case errors.Is(err, io.EOF):
|
||||
m.lg.Info("completed snapshot read; closing")
|
||||
default:
|
||||
m.lg.Warn("failed to receive from snapshot stream; closing", zap.Error(err))
|
||||
|
@ -85,12 +85,12 @@ func startMockServersUnix(count int) (ms *MockServers, err error) {
|
||||
for i := 0; i < count; i++ {
|
||||
f, err := os.CreateTemp(dir, "etcd-unix-so-")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to allocate temp file for unix socket: %v", err)
|
||||
return nil, fmt.Errorf("failed to allocate temp file for unix socket: %w", err)
|
||||
}
|
||||
fn := f.Name()
|
||||
err = os.Remove(fn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to remove temp file before creating unix socket: %v", err)
|
||||
return nil, fmt.Errorf("failed to remove temp file before creating unix socket: %w", err)
|
||||
}
|
||||
addrs = append(addrs, fn)
|
||||
}
|
||||
@ -110,7 +110,7 @@ func startMockServers(network string, addrs []string) (ms *MockServers, err erro
|
||||
for idx, addr := range addrs {
|
||||
ln, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to listen %v", err)
|
||||
return nil, fmt.Errorf("failed to listen %w", err)
|
||||
}
|
||||
ms.Servers[idx] = &MockServer{ln: ln, Network: network, Address: ln.Addr().String()}
|
||||
ms.StartAt(idx)
|
||||
@ -126,7 +126,7 @@ func (ms *MockServers) StartAt(idx int) (err error) {
|
||||
if ms.Servers[idx].ln == nil {
|
||||
ms.Servers[idx].ln, err = net.Listen(ms.Servers[idx].Network, ms.Servers[idx].Address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen %v", err)
|
||||
return fmt.Errorf("failed to listen %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ package clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
@ -52,7 +53,8 @@ func (rp retryPolicy) String() string {
|
||||
// handle itself even with retries.
|
||||
func isSafeRetryImmutableRPC(err error) bool {
|
||||
eErr := rpctypes.Error(err)
|
||||
if serverErr, ok := eErr.(rpctypes.EtcdError); ok && serverErr.Code() != codes.Unavailable {
|
||||
var serverErr rpctypes.EtcdError
|
||||
if errors.As(eErr, &serverErr) && serverErr.Code() != codes.Unavailable {
|
||||
// interrupted by non-transient server-side or gRPC-side error
|
||||
// client cannot handle itself (e.g. rpctypes.ErrCompacted)
|
||||
return false
|
||||
|
@ -349,10 +349,10 @@ func isContextError(err error) bool {
|
||||
}
|
||||
|
||||
func contextErrToGRPCErr(err error) error {
|
||||
switch err {
|
||||
case context.DeadlineExceeded:
|
||||
switch {
|
||||
case errors.Is(err, context.DeadlineExceeded):
|
||||
return status.Errorf(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled:
|
||||
case errors.Is(err, context.Canceled):
|
||||
return status.Errorf(codes.Canceled, err.Error())
|
||||
default:
|
||||
return status.Errorf(codes.Unknown, err.Error())
|
||||
|
@ -62,7 +62,7 @@ func SaveWithVersion(ctx context.Context, lg *zap.Logger, cfg clientv3.Config, d
|
||||
var f *os.File
|
||||
f, err = os.OpenFile(partpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileutil.PrivateFileMode)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not open %s (%v)", partpath, err)
|
||||
return "", fmt.Errorf("could not open %s (%w)", partpath, err)
|
||||
}
|
||||
lg.Info("created temporary db file", zap.String("path", partpath))
|
||||
|
||||
@ -95,7 +95,7 @@ func SaveWithVersion(ctx context.Context, lg *zap.Logger, cfg clientv3.Config, d
|
||||
)
|
||||
|
||||
if err = os.Rename(partpath, dbPath); err != nil {
|
||||
return resp.Version, fmt.Errorf("could not rename %s to %s (%v)", partpath, dbPath, err)
|
||||
return resp.Version, fmt.Errorf("could not rename %s to %s (%w)", partpath, dbPath, err)
|
||||
}
|
||||
lg.Info("saved", zap.String("path", dbPath))
|
||||
return resp.Version, nil
|
||||
|
@ -395,7 +395,7 @@ func (w *watcher) Close() (err error) {
|
||||
}
|
||||
}
|
||||
// Consider context.Canceled as a successful close
|
||||
if err == context.Canceled {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
@ -653,7 +653,7 @@ func (w *watchGRPCStream) run() {
|
||||
|
||||
// watch client failed on Recv; spawn another if possible
|
||||
case err := <-w.errc:
|
||||
if isHaltErr(w.ctx, err) || ContextError(w.ctx, err) == v3rpc.ErrNoLeader {
|
||||
if isHaltErr(w.ctx, err) || errors.Is(ContextError(w.ctx, err), v3rpc.ErrNoLeader) {
|
||||
closeErr = err
|
||||
return
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ func (f *featureGate) Set(value string) error {
|
||||
v := strings.TrimSpace(arr[1])
|
||||
boolValue, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value of %s=%s, err: %v", k, v, err)
|
||||
return fmt.Errorf("invalid value of %s=%s, err: %w", k, v, err)
|
||||
}
|
||||
m[k] = boolValue
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ func setFlagFromEnv(lg *zap.Logger, fs flagSetter, prefix, fname string, usedEnv
|
||||
if val != "" {
|
||||
usedEnvKey[key] = true
|
||||
if serr := fs.Set(fname, val); serr != nil {
|
||||
return fmt.Errorf("invalid value %q for %s: %v", val, key, serr)
|
||||
return fmt.Errorf("invalid value %q for %s: %w", val, key, serr)
|
||||
}
|
||||
if log && lg != nil {
|
||||
lg.Info(
|
||||
|
@ -63,7 +63,7 @@ func (ss *StubServer) Start(sopts []grpc.ServerOption, dopts ...grpc.DialOption)
|
||||
|
||||
lis, err := net.Listen(ss.Network, ss.Address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("net.Listen(%q, %q) = %v", ss.Network, ss.Address, err)
|
||||
return fmt.Errorf("net.Listen(%q, %q) = %w", ss.Network, ss.Address, err)
|
||||
}
|
||||
ss.Address = lis.Addr().String()
|
||||
ss.cleanups = append(ss.cleanups, func() { lis.Close() })
|
||||
|
@ -16,6 +16,7 @@ package ioutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
@ -28,7 +29,7 @@ func (rc *readerNilCloser) Close() error { return nil }
|
||||
func TestExactReadCloserExpectEOF(t *testing.T) {
|
||||
buf := bytes.NewBuffer(make([]byte, 10))
|
||||
rc := NewExactReadCloser(&readerNilCloser{buf}, 1)
|
||||
if _, err := rc.Read(make([]byte, 10)); err != ErrExpectEOF {
|
||||
if _, err := rc.Read(make([]byte, 10)); !errors.Is(err, ErrExpectEOF) {
|
||||
t.Fatalf("expected %v, got %v", ErrExpectEOF, err)
|
||||
}
|
||||
}
|
||||
@ -40,7 +41,7 @@ func TestExactReadCloserShort(t *testing.T) {
|
||||
if _, err := rc.Read(make([]byte, 10)); err != nil {
|
||||
t.Fatalf("Read expected nil err, got %v", err)
|
||||
}
|
||||
if err := rc.Close(); err != ErrShortRead {
|
||||
if err := rc.Close(); !errors.Is(err, ErrShortRead) {
|
||||
t.Fatalf("Close expected %v, got %v", ErrShortRead, err)
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package netutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
@ -70,14 +71,14 @@ func resolveTCPAddrs(ctx context.Context, lg *zap.Logger, urls [][]url.URL) ([][
|
||||
for i, u := range us {
|
||||
nu, err := url.Parse(u.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse %q (%v)", u.String(), err)
|
||||
return nil, fmt.Errorf("failed to parse %q (%w)", u.String(), err)
|
||||
}
|
||||
nus[i] = *nu
|
||||
}
|
||||
for i, u := range nus {
|
||||
h, err := resolveURL(ctx, lg, u)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve %q (%v)", u.String(), err)
|
||||
return nil, fmt.Errorf("failed to resolve %q (%w)", u.String(), err)
|
||||
}
|
||||
if h != "" {
|
||||
nus[i].Host = h
|
||||
@ -217,6 +218,6 @@ func stringsToURLs(us []string) ([]url.URL, error) {
|
||||
}
|
||||
|
||||
func IsNetworkTimeoutError(err error) bool {
|
||||
nerr, ok := err.(net.Error)
|
||||
return ok && nerr.Timeout()
|
||||
var nerr net.Error
|
||||
return errors.As(err, &nerr) && nerr.Timeout()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user