Here's how to define an io.Reader wrapper with the desired behavior:
// NewSleepyReader returns a reader that sleeps for duration
// after reading each block of num bytes from an underlying reader.
func NewSleepyReader(underlying io.Reader, num int, duration time.Duration) io.Reader {
return &sleepyReader{r: underlying, num: num, duration: duration}
}
type sleepyReader struct {
r io.Reader
duration time.Duration
num int
i int
}
func (sr *sleepyReader) Read(p []byte) (int, error) {
n, err := sr.r.Read(p[:min(len(p), sr.num-sr.i)])
sr.i += n
if sr.i >= sr.num {
time.Sleep(sr.duration)
sr.i = 0
}
return n, err
}
Use it like this in your application:
_, err := io.Copy(io.Discard, NewSleepyReader(r.Body, 10, time.Second))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}