Skip to content

Commit

Permalink
Merge pull request #104 from nyaruka/httpx_errs
Browse files Browse the repository at this point in the history
Use error constants for some httpx error cases
  • Loading branch information
rowanseymour authored Oct 28, 2023
2 parents 0a9d1f7 + f28c7dd commit a80bb60
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 26 deletions.
41 changes: 18 additions & 23 deletions httpx/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,41 +35,36 @@ func TestAccessConfig(t *testing.T) {
}))

tests := []struct {
url string
err string
url string
allowed bool
}{
// allowed
{"https://nyaruka.com", ""},
{"https://11.0.0.0", ""},
{"https://nyaruka.com", true},
{"https://11.0.0.0", true},

// denied by IP match
{"https://localhost/path", "request to localhost denied"},
{"https://LOCALHOST:80", "request to LOCALHOST denied"},
{"http://foo.localtest.me", "request to foo.localtest.me denied"},
{"https://127.0.0.1", "request to 127.0.0.1 denied"},
{"https://127.0.00.1", "?"}, // Go 1.19: "request to 127.0.00.1 denied", Go 1.20: "lookup 127.0.00.1: no such host"
{"https://[::1]:80", "request to ::1 denied"},
{"https://[0:0:0:0:0:0:0:1]:80", "request to 0:0:0:0:0:0:0:1 denied"},
{"https://[0000:0000:0000:0000:0000:0000:0000:0001]:80", "request to 0000:0000:0000:0000:0000:0000:0000:0001 denied"},
{"https://localhost/path", false},
{"https://LOCALHOST:80", false},
{"http://foo.localtest.me", false},
{"https://127.0.0.1", false},
{"https://[::1]:80", false},
{"https://[0:0:0:0:0:0:0:1]:80", false},
{"https://[0000:0000:0000:0000:0000:0000:0000:0001]:80", false},

// denied by network match
{"https://10.1.0.0", "request to 10.1.0.0 denied"},
{"https://10.0.1.0", "request to 10.0.1.0 denied"},
{"https://10.0.0.1", "request to 10.0.0.1 denied"},
{"https://[0:0:0:0:0:ffff:0a01:0000]:80", "request to 0:0:0:0:0:ffff:0a01:0000 denied"}, // 10.1.0.0 mapped to IPv6
{"https://10.1.0.0", false},
{"https://10.0.1.0", false},
{"https://10.0.0.1", false},
{"https://[0:0:0:0:0:ffff:0a01:0000]:80", false}, // 10.1.0.0 mapped to IPv6
}
for _, tc := range tests {
request, _ := http.NewRequest("GET", tc.url, nil)
_, err := httpx.DoTrace(http.DefaultClient, request, nil, access, -1)

if tc.err != "" {
if tc.err == "?" {
assert.Error(t, err)
} else {
assert.EqualError(t, err, tc.err, "error message mismatch for url %s", tc.url)
}
} else {
if tc.allowed {
assert.NoError(t, err)
} else {
assert.Equal(t, err, httpx.ErrAccessConfig, "error message mismatch for url %s", tc.url)
}
}
}
10 changes: 8 additions & 2 deletions httpx/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ import (
"github.com/pkg/errors"
)

// ErrResponseSize is returned when response size exceeds provided limit
var ErrResponseSize = errors.New("response body exceeds size limit")

// ErrAccessConfig is returned when provided access config prevents request
var ErrAccessConfig = errors.New("request not permitted by access config")

// Do makes the given HTTP request using the current requestor and retry config
func Do(client *http.Client, request *http.Request, retries *RetryConfig, access *AccessConfig) (*http.Response, error) {
r, _, err := do(client, request, retries, access)
Expand All @@ -29,7 +35,7 @@ func do(client *http.Client, request *http.Request, retries *RetryConfig, access
return nil, 0, err
}
if !allowed {
return nil, 0, errors.Errorf("request to %s denied", request.URL.Hostname())
return nil, 0, ErrAccessConfig
}
}

Expand Down Expand Up @@ -198,7 +204,7 @@ func readBody(response *http.Response, maxBodyBytes int) ([]byte, error) {

// if we have no remaining bytes, error because the body was too big
if bodyReader.(*io.LimitedReader).N <= 0 {
return nil, errors.Errorf("webhook response body exceeds %d bytes limit", maxBodyBytes)
return nil, ErrResponseSize
}

return bodyBytes, nil
Expand Down
3 changes: 2 additions & 1 deletion httpx/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ func TestMaxBodyBytes(t *testing.T) {
assert.Equal(t, string(testBody), string(trace.ResponseBody))

trace, err = call(10) // limit smaller than body
assert.EqualError(t, err, `webhook response body exceeds 10 bytes limit`)
assert.Equal(t, err, httpx.ErrResponseSize)
assert.EqualError(t, err, `response body exceeds size limit`)
assert.Equal(t, "HTTP/1.0 200 OK\r\nContent-Length: 26\r\n\r\n", string(trace.ResponseTrace))
assert.Equal(t, ``, string(trace.ResponseBody))
}
Expand Down

0 comments on commit a80bb60

Please sign in to comment.