f96cc9c955
* HTTPRanger * Migrate eestream library to use ReadCloser instead of Reader * Use MultiReadCloser instead of MultiReader * Adapt example cli cmds to latest serverbox changes * Close LazyReadCloser only if only generated * Close ReadClosers sequentially * Close response body on unexpected status code * Avoid double close of the pipe reader * Better formatting for imports * Exit instead of panicking
44 lines
1.1 KiB
Go
44 lines
1.1 KiB
Go
// Copyright (C) 2018 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package readcloser
|
|
|
|
import "io"
|
|
|
|
// MultiReadCloser is a MultiReader extension that returns a ReaderCloser
|
|
// that's the logical concatenation of the provided input readers.
|
|
// They're read sequentially. Once all inputs have returned EOF,
|
|
// Read will return EOF. If any of the readers return a non-nil,
|
|
// non-EOF error, Read will return that error.
|
|
func MultiReadCloser(readers ...io.ReadCloser) io.ReadCloser {
|
|
r := make([]io.Reader, len(readers))
|
|
for i := range readers {
|
|
r[i] = readers[i]
|
|
}
|
|
c := make([]io.Closer, len(readers))
|
|
for i := range readers {
|
|
c[i] = readers[i]
|
|
}
|
|
return &multiReadCloser{io.MultiReader(r...), c}
|
|
}
|
|
|
|
type multiReadCloser struct {
|
|
multireader io.Reader
|
|
closers []io.Closer
|
|
}
|
|
|
|
func (l *multiReadCloser) Read(p []byte) (n int, err error) {
|
|
return l.multireader.Read(p)
|
|
}
|
|
|
|
func (l *multiReadCloser) Close() error {
|
|
var firstErr error
|
|
for _, c := range l.closers {
|
|
err := c.Close()
|
|
if err != nil && firstErr == nil {
|
|
firstErr = err
|
|
}
|
|
}
|
|
return firstErr
|
|
}
|