diff --git a/datastore.go b/datastore.go index e536254..2d2638a 100644 --- a/datastore.go +++ b/datastore.go @@ -48,6 +48,8 @@ type DataStore interface { // should not be enabled any call to GetReader should return // tusd.ErrNotImplemented. The length of the resource is determined by // retrieving the offset using GetInfo. + // If the returned reader also implements the io.Closer interface, the + // Close() method will be invoked once everything has been read. GetReader(id string) (io.Reader, error) // Terminate an upload so any further requests to the resource, both reading // and writing, must return os.ErrNotExist or similar. diff --git a/get_test.go b/get_test.go index 60da8b4..17907e1 100644 --- a/get_test.go +++ b/get_test.go @@ -24,7 +24,21 @@ func (s getStore) GetInfo(id string) (FileInfo, error) { } func (s getStore) GetReader(id string) (io.Reader, error) { - return strings.NewReader("hello"), nil + return reader, nil +} + +type closingStringReader struct { + *strings.Reader + closed bool +} + +func (reader *closingStringReader) Close() error { + reader.closed = true + return nil +} + +var reader = &closingStringReader{ + Reader: strings.NewReader("hello"), } func TestGet(t *testing.T) { @@ -42,4 +56,8 @@ func TestGet(t *testing.T) { "Content-Length": "5", }, }).Run(handler, t) + + if !reader.closed { + t.Error("expected reader to be closed") + } } diff --git a/handler.go b/handler.go index ae2422c..8f6c14c 100644 --- a/handler.go +++ b/handler.go @@ -383,6 +383,11 @@ func (handler *Handler) getFile(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10)) w.WriteHeader(http.StatusOK) io.Copy(w, src) + + // Try to close the reader if the io.Closer interface is implemented + if closer, ok := src.(io.Closer); ok { + closer.Close() + } } // Terminate an upload permanently.