-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pull request: 2305 limit message size
Merge in DNS/adguard-home from 2305-limit-message-size to master Closes #2305. Squashed commit of the following: commit 6edd1e0 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Nov 23 14:03:36 2020 +0300 aghio: fix final inaccuracies commit 4dd382a Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Nov 23 13:59:10 2020 +0300 all: improve code quality commit 060f923 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Nov 23 13:10:57 2020 +0300 aghio: add validation to constructor commit f57a2f5 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 19:19:26 2020 +0300 all: fix minor inaccuracies commit 93462c7 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 19:13:23 2020 +0300 home: make test name follow convention commit 4922986 Merge: 1f5472a 046ec13 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 19:09:01 2020 +0300 Merge branch 'master' into 2305-limit-message-size commit 1f5472a Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 19:08:21 2020 +0300 aghio: improve readability commit 60dc706 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 18:44:08 2020 +0300 home: cover middleware with test commit bedf436 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 17:10:23 2020 +0300 aghio: improved error informativeness commit 682c5da Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Nov 20 13:37:51 2020 +0300 all: limit readers for ReadAll dealing with miscellanious data. commit 78c6dd8 Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Nov 19 20:07:43 2020 +0300 all: handle ReadAll calls dealing with request's bodies. commit bfe1a6f Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Nov 19 17:25:34 2020 +0300 home: add middlewares commit bbd1d49 Merge: 7b77c2c 62a8fe0 Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Nov 19 16:44:04 2020 +0300 Merge branch 'master' into 2305-limit-message-size commit 7b77c2c Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 17 15:33:33 2020 +0300 aghio: create package
- Loading branch information
Showing
15 changed files
with
412 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Package aghio contains extensions for io package's types and methods | ||
package aghio | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
) | ||
|
||
// LimitReachedError records the limit and the operation that caused it. | ||
type LimitReachedError struct { | ||
Limit int64 | ||
} | ||
|
||
// Error implements error interface for LimitReachedError. | ||
// TODO(a.garipov): Think about error string format. | ||
func (lre *LimitReachedError) Error() string { | ||
return fmt.Sprintf("attempted to read more than %d bytes", lre.Limit) | ||
} | ||
|
||
// limitedReadCloser is a wrapper for io.ReadCloser with limited reader and | ||
// dealing with agherr package. | ||
type limitedReadCloser struct { | ||
limit int64 | ||
n int64 | ||
rc io.ReadCloser | ||
} | ||
|
||
// Read implements Reader interface. | ||
func (lrc *limitedReadCloser) Read(p []byte) (n int, err error) { | ||
if lrc.n == 0 { | ||
return 0, &LimitReachedError{ | ||
Limit: lrc.limit, | ||
} | ||
} | ||
if int64(len(p)) > lrc.n { | ||
p = p[0:lrc.n] | ||
} | ||
n, err = lrc.rc.Read(p) | ||
lrc.n -= int64(n) | ||
return n, err | ||
} | ||
|
||
// Close implements Closer interface. | ||
func (lrc *limitedReadCloser) Close() error { | ||
return lrc.rc.Close() | ||
} | ||
|
||
// LimitReadCloser wraps ReadCloser to make it's Reader stop with | ||
// ErrLimitReached after n bytes read. | ||
func LimitReadCloser(rc io.ReadCloser, n int64) (limited io.ReadCloser, err error) { | ||
if n < 0 { | ||
return nil, fmt.Errorf("aghio: invalid n in LimitReadCloser: %d", n) | ||
} | ||
return &limitedReadCloser{ | ||
limit: n, | ||
n: n, | ||
rc: rc, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package aghio | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestLimitReadCloser(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
n int64 | ||
want error | ||
}{{ | ||
name: "positive", | ||
n: 1, | ||
want: nil, | ||
}, { | ||
name: "zero", | ||
n: 0, | ||
want: nil, | ||
}, { | ||
name: "negative", | ||
n: -1, | ||
want: fmt.Errorf("aghio: invalid n in LimitReadCloser: -1"), | ||
}} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
_, err := LimitReadCloser(nil, tc.n) | ||
assert.Equal(t, tc.want, err) | ||
}) | ||
} | ||
} | ||
|
||
func TestLimitedReadCloser_Read(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
limit int64 | ||
rStr string | ||
want int | ||
err error | ||
}{{ | ||
name: "perfectly_match", | ||
limit: 3, | ||
rStr: "abc", | ||
want: 3, | ||
err: nil, | ||
}, { | ||
name: "eof", | ||
limit: 3, | ||
rStr: "", | ||
want: 0, | ||
err: io.EOF, | ||
}, { | ||
name: "limit_reached", | ||
limit: 0, | ||
rStr: "abc", | ||
want: 0, | ||
err: &LimitReachedError{ | ||
Limit: 0, | ||
}, | ||
}, { | ||
name: "truncated", | ||
limit: 2, | ||
rStr: "abc", | ||
want: 2, | ||
err: nil, | ||
}} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
readCloser := ioutil.NopCloser(strings.NewReader(tc.rStr)) | ||
buf := make([]byte, tc.limit+1) | ||
|
||
lreader, err := LimitReadCloser(readCloser, tc.limit) | ||
assert.Nil(t, err) | ||
|
||
n, err := lreader.Read(buf) | ||
assert.Equal(t, n, tc.want) | ||
assert.Equal(t, tc.err, err) | ||
}) | ||
} | ||
} | ||
|
||
func TestLimitedReadCloser_LimitReachedError(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
want string | ||
err error | ||
}{{ | ||
name: "simplest", | ||
want: "attempted to read more than 0 bytes", | ||
err: &LimitReachedError{ | ||
Limit: 0, | ||
}, | ||
}} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
assert.Equal(t, tc.want, tc.err.Error()) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.