merge v0.23.0-rc changes
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
_ io.ReadCloser = (*RereadableReadCloser)(nil)
|
||||
_ Rereader = (*RereadableReadCloser)(nil)
|
||||
)
|
||||
|
||||
// Rereader defines an interface for rewindable readers.
|
||||
type Rereader interface {
|
||||
Reread()
|
||||
}
|
||||
|
||||
// RereadableReadCloser defines a wrapper around a io.ReadCloser reader
|
||||
// allowing to read the original reader multiple times.
|
||||
type RereadableReadCloser struct {
|
||||
io.ReadCloser
|
||||
|
||||
copy *bytes.Buffer
|
||||
active io.Reader
|
||||
}
|
||||
|
||||
// Read implements the standard io.Reader interface.
|
||||
//
|
||||
// It reads up to len(b) bytes into b and at at the same time writes
|
||||
// the read data into an internal bytes buffer.
|
||||
//
|
||||
// On EOF the r is "rewinded" to allow reading from r multiple times.
|
||||
func (r *RereadableReadCloser) Read(b []byte) (int, error) {
|
||||
if r.active == nil {
|
||||
if r.copy == nil {
|
||||
r.copy = &bytes.Buffer{}
|
||||
}
|
||||
r.active = io.TeeReader(r.ReadCloser, r.copy)
|
||||
}
|
||||
|
||||
n, err := r.active.Read(b)
|
||||
if err == io.EOF {
|
||||
r.Reread()
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Reread satisfies the [Rereader] interface and resets the r internal state to allow rereads.
|
||||
//
|
||||
// note: not named Reset to avoid conflicts with other reader interfaces.
|
||||
func (r *RereadableReadCloser) Reread() {
|
||||
if r.copy == nil || r.copy.Len() == 0 {
|
||||
return // nothing to reset or it has been already reset
|
||||
}
|
||||
|
||||
oldCopy := r.copy
|
||||
r.copy = &bytes.Buffer{}
|
||||
r.active = io.TeeReader(oldCopy, r.copy)
|
||||
}
|
||||
Reference in New Issue
Block a user