Skip to content

Commit

Permalink
routing/http: feat: limit the resp body payload
Browse files Browse the repository at this point in the history
  • Loading branch information
guseggert committed Dec 5, 2022
1 parent 10595c9 commit 30e59a1
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
8 changes: 7 additions & 1 deletion routing/http/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,15 @@ func WithProviderInfo(peerID peer.ID, addrs []multiaddr.Multiaddr) option {
// New creates a content routing API client.
// The Provider and identity parameters are option. If they are nil, the `Provide` method will not function.
func New(baseURL string, opts ...option) (*client, error) {
defaultHTTPClient := &http.Client{
Transport: &ResponseBodyLimitedTransport{
RoundTripper: http.DefaultTransport,
LimitBytes: 1 << 20,
},
}
client := &client{
baseURL: baseURL,
httpClient: http.DefaultClient,
httpClient: defaultHTTPClient,
validator: ipns.Validator{},
clock: clock.New(),
}
Expand Down
38 changes: 38 additions & 0 deletions routing/http/client/transport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package client

import (
"fmt"
"io"
"net/http"
)

type ResponseBodyLimitedTransport struct {
http.RoundTripper
LimitBytes int64
}

func (r *ResponseBodyLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := r.RoundTripper.RoundTrip(req)
if resp != nil && resp.Body != nil {
resp.Body = &limitReadCloser{
limit: r.LimitBytes,
ReadCloser: resp.Body,
}
}
return resp, err
}

type limitReadCloser struct {
limit int64
bytesRead int64
io.ReadCloser
}

func (l *limitReadCloser) Read(p []byte) (int, error) {
n, err := l.ReadCloser.Read(p)
l.bytesRead += int64(n)
if l.bytesRead > l.limit {
return 0, fmt.Errorf("reached read limit of %d bytes after reading %d bytes", l.limit, l.bytesRead)
}
return n, err
}
44 changes: 44 additions & 0 deletions routing/http/client/transport_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package client

import (
"io"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
)

type testServer struct {
bytesToWrite int
}

func (s *testServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
bytes := make([]byte, s.bytesToWrite)
for i := 0; i < s.bytesToWrite; i++ {
bytes[i] = 'a'
}
_, err := w.Write(bytes)
if err != nil {
panic(err)
}
}

func TestResponseBodyLimitedTransport(t *testing.T) {
server := httptest.NewServer(&testServer{bytesToWrite: 1 << 21})
t.Cleanup(server.Close)

client := server.Client()
client.Transport = &ResponseBodyLimitedTransport{
LimitBytes: 1 << 20,
RoundTripper: client.Transport,
}

resp, err := client.Get(server.URL)
if err != nil {
panic(err)
}
_, err = io.ReadAll(resp.Body)

assert.Contains(t, err.Error(), "reached read limit of 1048576 bytes after reading")
}

0 comments on commit 30e59a1

Please sign in to comment.