Skip to content

Commit 6dd8a29

Browse files
Merge pull request #18 from speakeasy-api/fix-url-resolving
fix: fixes resolving some relative and proxied URLs
2 parents 05f84ea + 51f5b72 commit 6dd8a29

File tree

3 files changed

+56
-22
lines changed

3 files changed

+56
-22
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/AlekSi/pointer v1.2.0
1212
github.com/gin-gonic/gin v1.8.1
1313
github.com/go-chi/chi/v5 v5.0.7
14+
github.com/gorilla/handlers v1.5.1
1415
github.com/gorilla/mux v1.8.0
1516
github.com/labstack/echo/v4 v4.7.2
1617
github.com/speakeasy-api/speakeasy-schemas v1.3.0

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
2828
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
2929
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
3030
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
31+
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
32+
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
3133
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
3234
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
3335
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
@@ -72,6 +74,8 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
7274
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
7375
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
7476
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
77+
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
78+
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
7579
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
7680
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
7781
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
@@ -115,8 +119,6 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
115119
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
116120
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
117121
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
118-
github.com/speakeasy-api/speakeasy-schemas v1.2.0 h1:raBOAba2M3ll9Xdw8yuJohtukonm3r9NytQqMFCSlOY=
119-
github.com/speakeasy-api/speakeasy-schemas v1.2.0/go.mod h1:g6NfrOjYLCJZp81ZLY2ksF7afC9BW9bL4Bg1V1oAFlw=
120122
github.com/speakeasy-api/speakeasy-schemas v1.3.0 h1:7Arm2d0/K9owEBQPmNon1KPERmf58g0Eg/NmPgXaEY0=
121123
github.com/speakeasy-api/speakeasy-schemas v1.3.0/go.mod h1:g6NfrOjYLCJZp81ZLY2ksF7afC9BW9bL4Bg1V1oAFlw=
122124
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

harbuilder.go

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import (
55
"context"
66
"net/http"
77
"net/http/httptest"
8+
"net/url"
89
"sort"
910
"strconv"
1011
"time"
1112

1213
"github.com/chromedp/cdproto/har"
14+
"github.com/gorilla/handlers"
1315
"github.com/speakeasy-api/speakeasy-go-sdk/internal/bodymasking"
1416
"github.com/speakeasy-api/speakeasy-go-sdk/internal/log"
1517
"go.uber.org/zap"
@@ -18,20 +20,7 @@ import (
1820
type harBuilder struct{}
1921

2022
func (h *harBuilder) buildHarFile(ctx context.Context, cw *captureWriter, r *http.Request, startTime time.Time, c *controller) *har.HAR {
21-
queryParams := r.URL.Query()
22-
for key, values := range queryParams {
23-
queryParams.Del(key)
24-
25-
for _, value := range values {
26-
mask, ok := c.queryStringMasks[key]
27-
if ok {
28-
value = mask
29-
}
30-
31-
queryParams.Add(key, value)
32-
}
33-
}
34-
r.URL.RawQuery = queryParams.Encode()
23+
resolvedURL := getResolvedURL(r, c)
3524

3625
return &har.HAR{
3726
Log: &har.Log{
@@ -40,15 +29,15 @@ func (h *harBuilder) buildHarFile(ctx context.Context, cw *captureWriter, r *htt
4029
Name: sdkName,
4130
Version: speakeasyVersion,
4231
},
43-
Comment: "request capture for " + r.URL.String(),
32+
Comment: "request capture for " + resolvedURL.String(),
4433
Entries: []*har.Entry{
4534
{
4635
StartedDateTime: startTime.Format(time.RFC3339Nano),
4736
Time: float64(timeSince(startTime).Milliseconds()),
48-
Request: h.getHarRequest(ctx, cw, r, c),
37+
Request: h.getHarRequest(ctx, cw, r, c, resolvedURL),
4938
Response: h.getHarResponse(ctx, cw, r, startTime, c),
50-
Connection: r.URL.Port(),
51-
ServerIPAddress: r.URL.Hostname(),
39+
Connection: resolvedURL.Port(),
40+
ServerIPAddress: resolvedURL.Hostname(),
5241
Cache: &har.Cache{},
5342
Timings: &har.Timings{
5443
Send: -1,
@@ -61,8 +50,50 @@ func (h *harBuilder) buildHarFile(ctx context.Context, cw *captureWriter, r *htt
6150
}
6251
}
6352

53+
func getResolvedURL(r *http.Request, c *controller) *url.URL {
54+
var url *url.URL
55+
56+
// Taking advantage of Gorilla's ProxyHeaders parsing to resolve Forwarded headers
57+
handlers.ProxyHeaders(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
58+
url = r.URL
59+
})).ServeHTTP(nil, r)
60+
61+
queryParams := url.Query()
62+
for key, values := range queryParams {
63+
queryParams.Del(key)
64+
65+
for _, value := range values {
66+
mask, ok := c.queryStringMasks[key]
67+
if ok {
68+
value = mask
69+
}
70+
71+
queryParams.Add(key, value)
72+
}
73+
}
74+
url.RawQuery = queryParams.Encode()
75+
76+
if url.IsAbs() {
77+
return url
78+
}
79+
80+
if url.Scheme == "" {
81+
if r.TLS != nil {
82+
url.Scheme = "https"
83+
} else {
84+
url.Scheme = "http"
85+
}
86+
}
87+
88+
if url.Host == "" {
89+
url.Host = r.Host
90+
}
91+
92+
return url
93+
}
94+
6495
//nolint:funlen
65-
func (h *harBuilder) getHarRequest(ctx context.Context, cw *captureWriter, r *http.Request, c *controller) *har.Request {
96+
func (h *harBuilder) getHarRequest(ctx context.Context, cw *captureWriter, r *http.Request, c *controller, url *url.URL) *har.Request {
6697
reqHeaders := []*har.NameValuePair{}
6798
for key, headers := range r.Header {
6899
for _, headerValue := range headers {
@@ -123,7 +154,7 @@ func (h *harBuilder) getHarRequest(ctx context.Context, cw *captureWriter, r *ht
123154

124155
return &har.Request{
125156
Method: r.Method,
126-
URL: r.URL.String(),
157+
URL: url.String(),
127158
Headers: reqHeaders,
128159
QueryString: reqQueryParams,
129160
BodySize: bodySize,

0 commit comments

Comments
 (0)