2021-04-26 08:08:37 +00:00
|
|
|
package handler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"sync/atomic"
|
|
|
|
)
|
|
|
|
|
|
|
|
// bodyReader is an io.Reader, which is intended to wrap the request
|
|
|
|
// body reader. If an error occurr during reading the request body, it
|
|
|
|
// will not return this error to the reading entity, but instead store
|
|
|
|
// the error and close the io.Reader, so that the error can be checked
|
|
|
|
// afterwards. This is helpful, so that the stores do not have to handle
|
|
|
|
// the error but this can instead be done in the handler.
|
|
|
|
// In addition, the bodyReader keeps track of how many bytes were read.
|
|
|
|
type bodyReader struct {
|
|
|
|
reader io.Reader
|
2022-03-19 22:21:17 +00:00
|
|
|
closer io.Closer
|
2021-04-26 08:08:37 +00:00
|
|
|
err error
|
|
|
|
bytesCounter int64
|
|
|
|
}
|
|
|
|
|
2022-03-19 22:21:17 +00:00
|
|
|
func newBodyReader(r io.ReadCloser, maxSize int64) *bodyReader {
|
2021-04-26 08:08:37 +00:00
|
|
|
return &bodyReader{
|
2022-03-19 22:21:17 +00:00
|
|
|
reader: io.LimitReader(r, maxSize),
|
|
|
|
closer: r,
|
2021-04-26 08:08:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *bodyReader) Read(b []byte) (int, error) {
|
|
|
|
if r.err != nil {
|
|
|
|
return 0, io.EOF
|
|
|
|
}
|
|
|
|
|
2023-06-13 14:17:46 +00:00
|
|
|
// TODO: Mask certain errors that we can safely ignore later on:
|
|
|
|
// io.EOF, io.UnexpectedEOF, io.ErrClosedPipe,
|
|
|
|
// read tcp 127.0.0.1:1080->127.0.0.1:56953: read: connection reset by peer,
|
|
|
|
// read tcp 127.0.0.1:1080->127.0.0.1:9375: i/o timeout
|
2021-04-26 08:08:37 +00:00
|
|
|
n, err := r.reader.Read(b)
|
|
|
|
atomic.AddInt64(&r.bytesCounter, int64(n))
|
|
|
|
r.err = err
|
|
|
|
|
|
|
|
if err == io.EOF {
|
|
|
|
return n, io.EOF
|
|
|
|
} else {
|
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r bodyReader) hasError() error {
|
|
|
|
if r.err == io.EOF {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *bodyReader) bytesRead() int64 {
|
|
|
|
return atomic.LoadInt64(&r.bytesCounter)
|
|
|
|
}
|
2022-03-19 22:21:17 +00:00
|
|
|
|
|
|
|
func (r *bodyReader) closeWithError(err error) {
|
|
|
|
r.closer.Close()
|
|
|
|
r.err = err
|
|
|
|
}
|