return new offset after successful PATCH request

This commit is contained in:
Acconut 2015-03-23 19:02:12 +01:00
parent e6f058eeca
commit 290fea5dac
7 changed files with 27 additions and 16 deletions

View File

@ -132,7 +132,7 @@ func (s concatFinalStore) GetReader(id string) (io.Reader, error) {
return nil, ErrNotFound
}
func (s concatFinalStore) WriteChunk(id string, offset int64, src io.Reader) error {
func (s concatFinalStore) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
if id != "foo" {
s.t.Error("unexpected file id")
}
@ -146,7 +146,7 @@ func (s concatFinalStore) WriteChunk(id string, offset int64, src io.Reader) err
s.t.Error("unexpected content")
}
return nil
return 10, nil
}
func TestConcatFinal(t *testing.T) {

View File

@ -37,7 +37,8 @@ type DataStore interface {
// return an os.ErrNotExist which will be interpretet as a 404 Not Found.
// It will also lock resources while they are written to ensure only one
// write happens per time.
WriteChunk(id string, offset int64, src io.Reader) error
// The function call must return the number of bytes written.
WriteChunk(id string, offset int64, src io.Reader) (int64, error)
// Read the fileinformation used to validate the offset and respond to HEAD
// requests. It may return an os.ErrNotExist which will be interpretet as a
// 404 Not Found.

View File

@ -42,20 +42,20 @@ func (store FileStore) NewUpload(info tusd.FileInfo) (id string, err error) {
return
}
func (store FileStore) WriteChunk(id string, offset int64, src io.Reader) error {
func (store FileStore) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
file, err := os.OpenFile(store.binPath(id), os.O_WRONLY|os.O_APPEND, defaultFilePerm)
if err != nil {
return err
return 0, err
}
defer file.Close()
n, err := io.Copy(file, src)
if n > 0 {
if err := store.setOffset(id, offset+n); err != nil {
return err
return 0, err
}
}
return err
return n, err
}
func (store FileStore) GetInfo(id string) (tusd.FileInfo, error) {

View File

@ -51,10 +51,13 @@ func TestFilestore(t *testing.T) {
}
// Write data to upload
err = store.WriteChunk(id, 0, strings.NewReader("hello world"))
bytesWritten, err := store.WriteChunk(id, 0, strings.NewReader("hello world"))
if err != nil {
t.Fatal(err)
}
if bytesWritten != int64(len("hello world")) {
t.Errorf("expected 11 bytes to be written")
}
// Check new offset
info, err = store.GetInfo(id)

View File

@ -314,12 +314,15 @@ func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) {
// Limit the
reader := io.LimitReader(r.Body, maxSize)
err = handler.dataStore.WriteChunk(id, offset, reader)
bytesWritten, err := handler.dataStore.WriteChunk(id, offset, reader)
if err != nil {
handler.sendError(w, err)
return
}
// Send new offset to client
w.Header().Set("Upload-Offset", strconv.FormatInt(offset+bytesWritten, 10))
w.WriteHeader(http.StatusNoContent)
}
@ -462,8 +465,9 @@ func (handler *Handler) fillFinalUpload(id string, uploads []string) error {
}
reader := io.MultiReader(readers...)
_, err := handler.dataStore.WriteChunk(id, 0, reader)
return handler.dataStore.WriteChunk(id, 0, reader)
return err
}
// Parse the Upload-Metadata header as defined in the File Creation extension.

View File

@ -12,8 +12,8 @@ type zeroStore struct{}
func (store zeroStore) NewUpload(info FileInfo) (string, error) {
return "", nil
}
func (store zeroStore) WriteChunk(id string, offset int64, src io.Reader) error {
return nil
func (store zeroStore) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
return 0, nil
}
func (store zeroStore) GetInfo(id string) (FileInfo, error) {

View File

@ -26,7 +26,7 @@ func (s patchStore) GetInfo(id string) (FileInfo, error) {
}, nil
}
func (s patchStore) WriteChunk(id string, offset int64, src io.Reader) error {
func (s patchStore) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
if s.called {
s.t.Errorf("WriteChunk must be called only once")
}
@ -45,7 +45,7 @@ func (s patchStore) WriteChunk(id string, offset int64, src io.Reader) error {
s.t.Errorf("Expected source to be 'hello'")
}
return nil
return 5, nil
}
func TestPatch(t *testing.T) {
@ -66,6 +66,9 @@ func TestPatch(t *testing.T) {
},
ReqBody: strings.NewReader("hello"),
Code: http.StatusNoContent,
ResHeader: map[string]string{
"Upload-Offset": "10",
},
}).Run(handler, t)
(&httpTest{
@ -120,7 +123,7 @@ func (s overflowPatchStore) GetInfo(id string) (FileInfo, error) {
}, nil
}
func (s overflowPatchStore) WriteChunk(id string, offset int64, src io.Reader) error {
func (s overflowPatchStore) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
if s.called {
s.t.Errorf("WriteChunk must be called only once")
}
@ -139,7 +142,7 @@ func (s overflowPatchStore) WriteChunk(id string, offset int64, src io.Reader) e
s.t.Errorf("Expected 15 bytes got %v", len(data))
}
return nil
return 15, nil
}
// noEOFReader implements io.Reader, io.Writer, io.Closer but does not return