fix(zarinhub): limit upstream response size
This commit is contained in:
@@ -13,6 +13,8 @@ import (
|
||||
"card-to-iban/internal/service"
|
||||
)
|
||||
|
||||
const maxResponseBodySize = 1 << 20
|
||||
|
||||
type Client struct {
|
||||
httpClient *http.Client
|
||||
endpointURL string
|
||||
@@ -95,7 +97,9 @@ func (c *Client) Convert(
|
||||
UpstreamHTTPStatus: resp.StatusCode,
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(
|
||||
io.LimitReader(resp.Body, maxResponseBodySize+1),
|
||||
)
|
||||
if err != nil {
|
||||
return result,
|
||||
fmt.Errorf(
|
||||
@@ -105,6 +109,14 @@ func (c *Client) Convert(
|
||||
)
|
||||
}
|
||||
|
||||
if len(body) > maxResponseBodySize {
|
||||
return result,
|
||||
fmt.Errorf(
|
||||
"%w: response body is too large",
|
||||
ErrInvalidResponse,
|
||||
)
|
||||
}
|
||||
|
||||
result.RawResponse = body
|
||||
|
||||
switch {
|
||||
|
||||
@@ -381,3 +381,36 @@ func TestClientReturnsTimeout(t *testing.T) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientRejectsOversizedResponse(t *testing.T) {
|
||||
server := httptest.NewServer(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
body := make([]byte, maxResponseBodySize+1)
|
||||
for index := range body {
|
||||
body[index] = 'x'
|
||||
}
|
||||
|
||||
if _, err := w.Write(body); err != nil {
|
||||
t.Errorf("write response: %v", err)
|
||||
}
|
||||
}),
|
||||
)
|
||||
defer server.Close()
|
||||
|
||||
client := NewClient(
|
||||
&http.Client{Timeout: time.Second},
|
||||
server.URL,
|
||||
"test-token",
|
||||
)
|
||||
|
||||
_, err := client.Convert(
|
||||
context.Background(),
|
||||
"6037997512345678",
|
||||
)
|
||||
|
||||
if !errors.Is(err, ErrInvalidResponse) {
|
||||
t.Fatalf("error = %v, want ErrInvalidResponse", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user