mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-03-23 23:19:19 +02:00
61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
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)
|
|
}
|