Skip to content

Commit df2f81c

Browse files
Juneezeeinancgumus
authored andcommitted
httpext: replace HTTP digest library
The current HTTP digest library, `github.com/Soontao/goHttpDigestClient`, has not been updated since March 2017 and is known to be buggy. This commit replaces it with `github.com/icholy/digest`, a more modern library that provides an `http.RoundTripper` implementation, allowing digest challenges to be reused. This aligns well with our use case. Closes #800. Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
1 parent ed02613 commit df2f81c

File tree

23 files changed

+1074
-553
lines changed

23 files changed

+1074
-553
lines changed

go.mod

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ require (
88
buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.36.5-20240802094132-5b212ab78fb7.1
99
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
1010
github.com/PuerkitoBio/goquery v1.9.2
11-
github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5
1211
github.com/andybalholm/brotli v1.1.1
1312
github.com/chromedp/cdproto v0.0.0-20240919203636-12af5e8a671f
1413
github.com/evanw/esbuild v0.25.0
@@ -21,6 +20,7 @@ require (
2120
github.com/grafana/xk6-dashboard v0.7.5
2221
github.com/grafana/xk6-redis v0.3.3
2322
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
23+
github.com/icholy/digest v1.1.0
2424
github.com/influxdata/influxdb1-client v0.0.0-20190402204710-8ff2fc3824fc
2525
github.com/jhump/protoreflect v1.17.0
2626
github.com/klauspost/compress v1.18.0
@@ -31,7 +31,8 @@ require (
3131
github.com/mstoykov/atlas v0.0.0-20220811071828-388f114305dd
3232
github.com/mstoykov/envconfig v1.5.0
3333
github.com/mstoykov/k6-taskqueue-lib v0.1.3
34-
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
34+
github.com/prometheus/client_golang v1.16.0
35+
github.com/prometheus/client_model v0.4.0
3536
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e
3637
github.com/sirupsen/logrus v1.9.3
3738
github.com/spf13/afero v1.1.2
@@ -84,8 +85,6 @@ require (
8485
github.com/nxadm/tail v1.4.11 // indirect
8586
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
8687
github.com/pmezard/go-difflib v1.0.0 // indirect
87-
github.com/prometheus/client_golang v1.16.0
88-
github.com/prometheus/client_model v0.4.0
8988
github.com/prometheus/common v0.42.0 // indirect
9089
github.com/prometheus/procfs v0.10.1 // indirect
9190
github.com/r3labs/sse/v2 v2.10.0 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
1010
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
1111
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
1212
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
13-
github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5 h1:k+1+doEm31k0rRjCjLnGG3YRkuO9ljaEyS2ajZd6GK8=
14-
github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5/go.mod h1:5Q4+CyR7+Q3VMG8f78ou+QSX/BNUNUx5W48eFRat8DQ=
1513
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
1614
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
1715
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
@@ -91,6 +89,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa
9189
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
9290
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
9391
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
92+
github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4=
93+
github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y=
9494
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
9595
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
9696
github.com/influxdata/influxdb1-client v0.0.0-20190402204710-8ff2fc3824fc h1:KpMgaYJRieDkHZJWY3LMafvtqS/U8xX6+lUN+OKpl/Y=
@@ -127,8 +127,6 @@ github.com/mstoykov/envconfig v1.5.0 h1:E2FgWf73BQt0ddgn7aoITkQHmgwAcHup1s//MsS5
127127
github.com/mstoykov/envconfig v1.5.0/go.mod h1:vk/d9jpexY2Z9Bb0uB4Ndesss1Sr0Z9ZiGUrg5o9VGk=
128128
github.com/mstoykov/k6-taskqueue-lib v0.1.3 h1:sdiSc5NEK/qpQkTQe505vgRYQocZevdO9ON+yMudFqo=
129129
github.com/mstoykov/k6-taskqueue-lib v0.1.3/go.mod h1:e9R2vtLFHCKT+CMiEjTJVMQiJAi17M1KiXXRs7FYc6w=
130-
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
131-
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
132130
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
133131
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
134132
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
@@ -345,5 +343,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
345343
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
346344
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
347345
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
346+
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
347+
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
348348
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
349349
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package httpext
22

33
import (
4-
"io"
54
"net/http"
65

7-
digest "github.com/Soontao/goHttpDigestClient"
6+
"github.com/icholy/digest"
87
)
98

109
type digestTransport struct {
@@ -13,52 +12,20 @@ type digestTransport struct {
1312

1413
// RoundTrip handles digest auth by behaving like an http.RoundTripper
1514
//
16-
// TODO: fix - this is a preliminary solution and is somewhat broken! we're
17-
// always making 2 HTTP requests when digest authentication is enabled... we
18-
// should cache the nonces and behave more like a browser... or we should
19-
// ditch the hacky http.RoundTripper approach and write our own client...
20-
//
21-
// Github issue: https://github.com/k6io/k6/issues/800
15+
// GitHub PR: https://github.com/grafana/k6/pull/4599
2216
func (t digestTransport) RoundTrip(req *http.Request) (*http.Response, error) {
23-
// Make the initial request authentication params to compute the
24-
// authorization header
2517
username := req.URL.User.Username()
2618
password, _ := req.URL.User.Password()
2719

2820
// Remove the user data from the URL to avoid sending the authorization
2921
// header for basic auth
3022
req.URL.User = nil
3123

32-
noAuthResponse, err := t.originalTransport.RoundTrip(req)
33-
if err != nil || noAuthResponse.StatusCode != http.StatusUnauthorized {
34-
// If there was an error, or if the remote server didn't respond with
35-
// status 401, we simply return, so the upstream code can deal with it.
36-
return noAuthResponse, err
37-
}
38-
39-
respBody, err := io.ReadAll(noAuthResponse.Body)
40-
if err != nil {
41-
return nil, err
42-
}
43-
_ = noAuthResponse.Body.Close()
44-
45-
// Calculate the Authorization header
46-
// TODO: determine if we actually need the body, since I'm not sure that's
47-
// what the `entity` means... maybe a moot point if we change the used
48-
// digest auth library...
49-
challenge := digest.GetChallengeFromHeader(&noAuthResponse.Header)
50-
challenge.ComputeResponse(req.Method, req.URL.RequestURI(), string(respBody), username, password)
51-
authorization := challenge.ToAuthorizationStr()
52-
req.Header.Set(digest.KEY_AUTHORIZATION, authorization)
53-
54-
if req.GetBody != nil {
55-
// Reset the request body if we need to
56-
req.Body, err = req.GetBody()
57-
if err != nil {
58-
return nil, err
59-
}
24+
digestTr := &digest.Transport{
25+
Username: username,
26+
Password: password,
27+
Transport: t.originalTransport,
6028
}
6129

62-
// Actually make the HTTP request with the proper Authorization
63-
return t.originalTransport.RoundTrip(req)
30+
return digestTr.RoundTrip(req)
6431
}

lib/netext/httpext/httpdebug_transport.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"net/http"
66
"net/http/httputil"
77

8-
uuid "github.com/nu7hatch/gouuid"
8+
"github.com/google/uuid"
99
"github.com/sirupsen/logrus"
1010
)
1111

@@ -22,10 +22,10 @@ type httpDebugTransport struct {
2222
// - https://github.com/k6io/k6/issues/1042
2323
// - https://github.com/k6io/k6/issues/774
2424
func (t httpDebugTransport) RoundTrip(req *http.Request) (*http.Response, error) {
25-
id, _ := uuid.NewV4()
26-
t.debugRequest(req, id.String())
25+
id := uuid.NewString()
26+
t.debugRequest(req, id)
2727
resp, err := t.originalTransport.RoundTrip(req)
28-
t.debugResponse(resp, id.String())
28+
t.debugResponse(resp, id)
2929
return resp, err
3030
}
3131

lib/netext/httpext/request.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,12 @@ func MakeRequest(ctx context.Context, state *lib.State, preq *ParsedHTTPRequest)
205205
}
206206

207207
if preq.Auth == "digest" {
208-
// Until digest authentication is refactored, the first response will always
209-
// be a 401 error, so we expect that.
208+
// The first response will either succeed or return a 401.
210209
if tracerTransport.responseCallback != nil {
211210
originalResponseCallback := tracerTransport.responseCallback
212211
tracerTransport.responseCallback = func(status int) bool {
213212
tracerTransport.responseCallback = originalResponseCallback
214-
return status == 401
213+
return status == 401 || originalResponseCallback(status)
215214
}
216215
}
217216
transport = digestTransport{originalTransport: transport}

vendor/github.com/Soontao/goHttpDigestClient/.gitignore

Lines changed: 0 additions & 33 deletions
This file was deleted.

vendor/github.com/Soontao/goHttpDigestClient/README.md

Lines changed: 0 additions & 26 deletions
This file was deleted.

vendor/github.com/Soontao/goHttpDigestClient/challenge.go

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)