Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: "1.26"
check-latest: true
- name: Install golangci-lint
# Build from source with the CI Go toolchain so the linter binary's Go
# version matches the module's `go 1.26` directive. golangci-lint refuses
# to run when it was built with an older Go than the target module, which
# the prebuilt action binaries currently are.
run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
run: golangci-lint run ./...
8 changes: 8 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ linters:
- name: exported
arguments:
- disableStutteringCheck
exclusions:
rules:
# Test stub transporters return in-memory bodies (NopCloser / http.NoBody)
# that hold no resources, and many cases deliberately discard the response
# to assert an error. bodyclose stays enforced for non-test code.
- path: _test\.go
linters:
- bodyclose

formatters:
enable:
Expand Down
2 changes: 1 addition & 1 deletion auth/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
func okTransport(seen *http.Request) transporterFunc {
return func(req *http.Request) (*http.Response, error) {
*seen = *req
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
}
}

Expand Down
8 changes: 4 additions & 4 deletions auth/bearer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestBearerAttachesHeaderAndCaches(t *testing.T) {
var seen string
transport := transporterFunc(func(req *http.Request) (*http.Response, error) {
seen = req.Header.Get(header.Authorization)
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
})

cred := &countingCredential{token: "abc123", exp: time.Now().Add(time.Hour)}
Expand Down Expand Up @@ -90,7 +90,7 @@ func TestBearerPropagatesCredentialError(t *testing.T) {
cred := errCredential{err: wantErr}
pl := pipeline.New(
transporterFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{StatusCode: 200, Body: http.NoBody, Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody, Request: req}, nil
}),
auth.NewBearerTokenPolicy(cred),
)
Expand All @@ -109,7 +109,7 @@ func TestBearerSharedCacheReusesToken(t *testing.T) {

run := func(p *auth.BearerTokenPolicy) {
transport := transporterFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
})
pl := pipeline.New(transport, p)
req, _ := http.NewRequest(http.MethodGet, "https://api.example.test/", nil)
Expand Down Expand Up @@ -142,7 +142,7 @@ func TestBearerRefetchesNearExpiryToken(t *testing.T) {
cred := &countingCredential{token: "tok", exp: time.Now().Add(time.Minute)}
pl := pipeline.New(
transporterFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
}),
auth.NewBearerTokenPolicy(cred, "scope"),
)
Expand Down
4 changes: 2 additions & 2 deletions auth/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package auth

import (
"crypto/md5"
"crypto/md5" //nolint:gosec // G501: MD5 is mandated by RFC 7616 Digest; it is a protocol primitive here, not used for security-sensitive hashing.
"crypto/rand"
"crypto/sha256"
"encoding/hex"
Expand Down Expand Up @@ -70,7 +70,7 @@ func (p *DigestAuthPolicy) Do(req *pipeline.Request) (*http.Response, error) {
return resp, nil
}
if rerr := req.RewindBody(); rerr != nil {
return resp, nil // non-replayable body: cannot retry, surface the 401
return resp, nil //nolint:nilerr // intentional: a non-replayable body cannot be retried, so the 401 response is surfaced unchanged.
}
nc := p.adopt(ch)
hdr, herr := p.authorization(ch, nc, raw.Method, raw.URL.RequestURI())
Expand Down
2 changes: 1 addition & 1 deletion client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (f transporterFunc) Do(req *http.Request) (*http.Response, error) { return
func captureTransport(captured **http.Request) transporterFunc {
return func(r *http.Request) (*http.Response, error) {
*captured = r
return &http.Response{StatusCode: 200, Body: http.NoBody, Request: r}, nil
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody, Request: r}, nil
}
}

Expand Down
4 changes: 2 additions & 2 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import (
"net/http"
"net/http/httptest"

"github.com/dexpace/go-sdk"
dexpace "github.com/dexpace/go-sdk"
"github.com/dexpace/go-sdk/retry"
)

// ExampleClient_Do shows the smallest end-to-end use: build a client, send a
// standard *http.Request, read the response.
func ExampleClient_Do() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprint(w, "pong")
_, _ = fmt.Fprint(w, "pong")
}))
defer srv.Close()

Expand Down
2 changes: 1 addition & 1 deletion idempotency/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type transporterFunc func(*http.Request) (*http.Response, error)
func (f transporterFunc) Do(req *http.Request) (*http.Response, error) { return f(req) }

func okResp(req *http.Request) (*http.Response, error) {
return &http.Response{StatusCode: 200, Body: http.NoBody, Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody, Request: req}, nil
}

func runPolicy(t *testing.T, p *Policy, req *http.Request) *http.Request {
Expand Down
2 changes: 1 addition & 1 deletion instrumentation/tracing_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type transporterFunc func(*http.Request) (*http.Response, error)
func (f transporterFunc) Do(req *http.Request) (*http.Response, error) { return f(req) }

func okResp(req *http.Request) (*http.Response, error) {
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
}

type fakeSpan struct {
Expand Down
2 changes: 1 addition & 1 deletion logging/logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestLoggingRedactsQuerySecret(t *testing.T) {
var buf bytes.Buffer
logger := slog.New(slog.NewTextHandler(&buf, nil))
transport := transporterFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("")), Request: req}, nil
})
pl := pipeline.New(transport, logging.NewPolicy(logging.Options{Logger: logger}))

Expand Down
10 changes: 8 additions & 2 deletions pagination/strategies.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ func NewPageNumber[T any](startPage int, fetch func(ctx context.Context, page in

// NewLinkHeader returns a Pager that follows RFC 8288 Link headers. fetch is
// called with the next URL (empty for the first page) and returns the page's
// items and the HTTP response whose Link header carries the next URL.
// items and the HTTP response whose Link header carries the next URL. The Pager
// owns each returned response and closes its body after reading the Link header,
// so fetch must finish reading the body (to produce its items) before returning.
//
// The next URL is taken from the server-controlled Link header, so fetch should
// validate or trust the URL's host before dialing it to avoid SSRF.
Expand All @@ -50,7 +52,11 @@ func NewLinkHeader[T any](fetch func(ctx context.Context, url string) ([]T, *htt
if err != nil {
return Page[T]{}, err
}
return Page[T]{Items: items, NextToken: NextLink(resp)}, nil
next := NextLink(resp)
if resp != nil && resp.Body != nil {
_ = resp.Body.Close()
}
return Page[T]{Items: items, NextToken: next}, nil
}
return New(tokenFetch, opts...)
}
Expand Down
2 changes: 1 addition & 1 deletion pipeline/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestSetContextIgnoresNil(t *testing.T) {
t.Parallel()

p := pipeline.PolicyFunc(func(req *pipeline.Request) (*http.Response, error) {
req.SetContext(nil) // must not panic
req.SetContext(nil) //nolint:staticcheck // SA1012: intentionally nil to verify SetContext ignores a nil context (must not panic).
return req.Next()
})
pl := pipeline.New(transporterFunc(okResponse), p)
Expand Down
2 changes: 1 addition & 1 deletion pipeline/stage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestStagesAreOrdered(t *testing.T) {
pipeline.StageLogging,
}
for i := 1; i < len(ordered); i++ {
if !(ordered[i-1] < ordered[i]) {
if ordered[i-1] >= ordered[i] {
t.Fatalf("stage %d not less than stage %d", ordered[i-1], ordered[i])
}
}
Expand Down
2 changes: 1 addition & 1 deletion transport/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func New(opts ...Option) *Transport {

// Do performs the HTTP round-trip. It satisfies pipeline.Transporter.
func (t *Transport) Do(req *http.Request) (*http.Response, error) {
return t.client.Do(req)
return t.client.Do(req) //nolint:gosec // G704: this is the SDK's HTTP transport; issuing the caller's own request is its sole purpose.
}

// defaultRoundTripper clones http.DefaultTransport so global state is untouched,
Expand Down
Loading