From 86dc420ebe7545d7091325c711e08ed969e93772 Mon Sep 17 00:00:00 2001 From: Naren Venkataraman Date: Wed, 4 Nov 2015 04:16:41 -0500 Subject: [PATCH 1/5] Fix Content-Length/Body Len Mismatch --- handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handler.go b/handler.go index cfa0c47..9b0fb9f 100644 --- a/handler.go +++ b/handler.go @@ -446,7 +446,7 @@ func (handler *Handler) sendError(w http.ResponseWriter, r *http.Request, err er w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Length", strconv.Itoa(len(reason))) w.WriteHeader(status) - w.Write([]byte(err.Error() + "\n")) + w.Write([]byte(err.Error())) } // Make an absolute URLs to the given upload id. If the base path is absolute From 1f6aac2a49934fc512d1215e233570d4c34bf64a Mon Sep 17 00:00:00 2001 From: Naren Venkataraman Date: Wed, 4 Nov 2015 04:23:09 -0500 Subject: [PATCH 2/5] Make sure PATCH request has application/offset+octet-stream --- handler.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/handler.go b/handler.go index 9b0fb9f..9051b43 100644 --- a/handler.go +++ b/handler.go @@ -22,6 +22,7 @@ var reExtractFileID = regexp.MustCompile(`([^/]+)\/?$`) var ( ErrUnsupportedVersion = errors.New("unsupported version") ErrMaxSizeExceeded = errors.New("maximum size exceeded") + ErrInvalidContentType = errors.New("missing or invalid Content-Type header") ErrInvalidUploadLength = errors.New("missing or invalid Upload-Length header") ErrInvalidOffset = errors.New("missing or invalid Upload-Offset header") ErrNotFound = errors.New("upload not found") @@ -38,6 +39,7 @@ var ( var ErrStatusCodes = map[error]int{ ErrUnsupportedVersion: http.StatusPreconditionFailed, ErrMaxSizeExceeded: http.StatusRequestEntityTooLarge, + ErrInvalidContentType: http.StatusBadRequest, ErrInvalidUploadLength: http.StatusBadRequest, ErrInvalidOffset: http.StatusBadRequest, ErrNotFound: http.StatusNotFound, @@ -275,6 +277,13 @@ func (handler *Handler) headFile(w http.ResponseWriter, r *http.Request) { // Add a chunk to an upload. Only allowed if the upload is not locked and enough // space is left. func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) { + + //Check for presence of application/offset+octet-stream + if r.Header.Get("Content-Type") != "application/offset+octet-stream" { + handler.sendError(w, r, ErrInvalidContentType) + return + } + id := r.URL.Query().Get(":id") // Ensure file is not locked From e451dc5f65492fc323b7cdbc480e69dbe3e2d0f9 Mon Sep 17 00:00:00 2001 From: Naren Venkataraman Date: Wed, 4 Nov 2015 04:33:32 -0500 Subject: [PATCH 3/5] Make sure Upload-Offset in PATCH request is greater than 0 --- handler.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/handler.go b/handler.go index 9051b43..a44be99 100644 --- a/handler.go +++ b/handler.go @@ -284,6 +284,13 @@ func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) { return } + //Check for presence of a valid Upload-Offset Header + offset, err := strconv.ParseInt(r.Header.Get("Upload-Offset"), 10, 64) + if err != nil || offset < 0 { + handler.sendError(w, r, ErrInvalidOffset) + return + } + id := r.URL.Query().Get(":id") // Ensure file is not locked @@ -312,13 +319,6 @@ func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) { return } - // Ensure the offsets match - offset, err := strconv.ParseInt(r.Header.Get("Upload-Offset"), 10, 64) - if err != nil { - handler.sendError(w, r, ErrInvalidOffset) - return - } - if offset != info.Offset { handler.sendError(w, r, ErrIllegalOffset) return From db67b862aef73b1a74b05cabd099e01001e8b2a4 Mon Sep 17 00:00:00 2001 From: Naren Venkataraman Date: Wed, 4 Nov 2015 04:37:37 -0500 Subject: [PATCH 4/5] s/ErrIllegalOffset/ErrMismatchOffset --- handler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/handler.go b/handler.go index a44be99..72dc48f 100644 --- a/handler.go +++ b/handler.go @@ -27,7 +27,7 @@ var ( ErrInvalidOffset = errors.New("missing or invalid Upload-Offset header") ErrNotFound = errors.New("upload not found") ErrFileLocked = errors.New("file currently locked") - ErrIllegalOffset = errors.New("illegal offset") + ErrMismatchOffset = errors.New("mismatched offset") ErrSizeExceeded = errors.New("resource's size exceeded") ErrNotImplemented = errors.New("feature not implemented") ErrUploadNotFinished = errors.New("one of the partial uploads is not finished") @@ -44,7 +44,7 @@ var ErrStatusCodes = map[error]int{ ErrInvalidOffset: http.StatusBadRequest, ErrNotFound: http.StatusNotFound, ErrFileLocked: 423, // Locked (WebDAV) (RFC 4918) - ErrIllegalOffset: http.StatusConflict, + ErrMismatchOffset: http.StatusConflict, ErrSizeExceeded: http.StatusRequestEntityTooLarge, ErrNotImplemented: http.StatusNotImplemented, ErrUploadNotFinished: http.StatusBadRequest, @@ -320,7 +320,7 @@ func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) { } if offset != info.Offset { - handler.sendError(w, r, ErrIllegalOffset) + handler.sendError(w, r, ErrMismatchOffset) return } From 7898128700f4c2a51e41bd82a8a7d596e95b622e Mon Sep 17 00:00:00 2001 From: Naren Venkataraman Date: Wed, 4 Nov 2015 04:56:32 -0500 Subject: [PATCH 5/5] Fix tests --- handler_test.go | 1 + patch_test.go | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/handler_test.go b/handler_test.go index 818d2bf..c1cb07b 100644 --- a/handler_test.go +++ b/handler_test.go @@ -117,6 +117,7 @@ func TestMethodOverride(t *testing.T) { ReqHeader: map[string]string{ "Tus-Resumable": "1.0.0", "Upload-Offset": "5", + "Content-Type": "application/offset+octet-stream", "X-HTTP-Method-Override": "PATCH", }, ReqBody: strings.NewReader("hello"), diff --git a/patch_test.go b/patch_test.go index e67d859..f7268cd 100644 --- a/patch_test.go +++ b/patch_test.go @@ -62,6 +62,7 @@ func TestPatch(t *testing.T) { URL: "yes", ReqHeader: map[string]string{ "Tus-Resumable": "1.0.0", + "Content-Type": "application/offset+octet-stream", "Upload-Offset": "5", }, ReqBody: strings.NewReader("hello"), @@ -77,6 +78,7 @@ func TestPatch(t *testing.T) { URL: "no", ReqHeader: map[string]string{ "Tus-Resumable": "1.0.0", + "Content-Type": "application/offset+octet-stream", "Upload-Offset": "5", }, Code: http.StatusNotFound, @@ -88,6 +90,7 @@ func TestPatch(t *testing.T) { URL: "yes", ReqHeader: map[string]string{ "Tus-Resumable": "1.0.0", + "Content-Type": "application/offset+octet-stream", "Upload-Offset": "4", }, Code: http.StatusConflict, @@ -99,6 +102,7 @@ func TestPatch(t *testing.T) { URL: "yes", ReqHeader: map[string]string{ "Tus-Resumable": "1.0.0", + "Content-Type": "application/offset+octet-stream", "Upload-Offset": "5", }, ReqBody: strings.NewReader("hellothisismorethan15bytes"), @@ -194,6 +198,7 @@ func TestPatchOverflow(t *testing.T) { URL: "yes", ReqHeader: map[string]string{ "Tus-Resumable": "1.0.0", + "Content-Type": "application/offset+octet-stream", "Upload-Offset": "5", "Content-Length": "3", },