Merge pull request #27 from vayam/master

Protocol Conformance + Bug fixes
This commit is contained in:
Marius 2015-11-09 21:51:53 +01:00
commit b6b65c5dee
3 changed files with 26 additions and 11 deletions

View File

@ -22,11 +22,12 @@ var reExtractFileID = regexp.MustCompile(`([^/]+)\/?$`)
var ( var (
ErrUnsupportedVersion = errors.New("unsupported version") ErrUnsupportedVersion = errors.New("unsupported version")
ErrMaxSizeExceeded = errors.New("maximum size exceeded") ErrMaxSizeExceeded = errors.New("maximum size exceeded")
ErrInvalidContentType = errors.New("missing or invalid Content-Type header")
ErrInvalidUploadLength = errors.New("missing or invalid Upload-Length header") ErrInvalidUploadLength = errors.New("missing or invalid Upload-Length header")
ErrInvalidOffset = errors.New("missing or invalid Upload-Offset header") ErrInvalidOffset = errors.New("missing or invalid Upload-Offset header")
ErrNotFound = errors.New("upload not found") ErrNotFound = errors.New("upload not found")
ErrFileLocked = errors.New("file currently locked") ErrFileLocked = errors.New("file currently locked")
ErrIllegalOffset = errors.New("illegal offset") ErrMismatchOffset = errors.New("mismatched offset")
ErrSizeExceeded = errors.New("resource's size exceeded") ErrSizeExceeded = errors.New("resource's size exceeded")
ErrNotImplemented = errors.New("feature not implemented") ErrNotImplemented = errors.New("feature not implemented")
ErrUploadNotFinished = errors.New("one of the partial uploads is not finished") ErrUploadNotFinished = errors.New("one of the partial uploads is not finished")
@ -38,11 +39,12 @@ var (
var ErrStatusCodes = map[error]int{ var ErrStatusCodes = map[error]int{
ErrUnsupportedVersion: http.StatusPreconditionFailed, ErrUnsupportedVersion: http.StatusPreconditionFailed,
ErrMaxSizeExceeded: http.StatusRequestEntityTooLarge, ErrMaxSizeExceeded: http.StatusRequestEntityTooLarge,
ErrInvalidContentType: http.StatusBadRequest,
ErrInvalidUploadLength: http.StatusBadRequest, ErrInvalidUploadLength: http.StatusBadRequest,
ErrInvalidOffset: http.StatusBadRequest, ErrInvalidOffset: http.StatusBadRequest,
ErrNotFound: http.StatusNotFound, ErrNotFound: http.StatusNotFound,
ErrFileLocked: 423, // Locked (WebDAV) (RFC 4918) ErrFileLocked: 423, // Locked (WebDAV) (RFC 4918)
ErrIllegalOffset: http.StatusConflict, ErrMismatchOffset: http.StatusConflict,
ErrSizeExceeded: http.StatusRequestEntityTooLarge, ErrSizeExceeded: http.StatusRequestEntityTooLarge,
ErrNotImplemented: http.StatusNotImplemented, ErrNotImplemented: http.StatusNotImplemented,
ErrUploadNotFinished: http.StatusBadRequest, ErrUploadNotFinished: http.StatusBadRequest,
@ -275,6 +277,20 @@ 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 // Add a chunk to an upload. Only allowed if the upload is not locked and enough
// space is left. // space is left.
func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) { 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
}
//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") id := r.URL.Query().Get(":id")
// Ensure file is not locked // Ensure file is not locked
@ -303,15 +319,8 @@ func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) {
return 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 { if offset != info.Offset {
handler.sendError(w, r, ErrIllegalOffset) handler.sendError(w, r, ErrMismatchOffset)
return return
} }
@ -446,7 +455,7 @@ func (handler *Handler) sendError(w http.ResponseWriter, r *http.Request, err er
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
w.Header().Set("Content-Length", strconv.Itoa(len(reason))) w.Header().Set("Content-Length", strconv.Itoa(len(reason)))
w.WriteHeader(status) 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 // Make an absolute URLs to the given upload id. If the base path is absolute

View File

@ -117,6 +117,7 @@ func TestMethodOverride(t *testing.T) {
ReqHeader: map[string]string{ ReqHeader: map[string]string{
"Tus-Resumable": "1.0.0", "Tus-Resumable": "1.0.0",
"Upload-Offset": "5", "Upload-Offset": "5",
"Content-Type": "application/offset+octet-stream",
"X-HTTP-Method-Override": "PATCH", "X-HTTP-Method-Override": "PATCH",
}, },
ReqBody: strings.NewReader("hello"), ReqBody: strings.NewReader("hello"),

View File

@ -62,6 +62,7 @@ func TestPatch(t *testing.T) {
URL: "yes", URL: "yes",
ReqHeader: map[string]string{ ReqHeader: map[string]string{
"Tus-Resumable": "1.0.0", "Tus-Resumable": "1.0.0",
"Content-Type": "application/offset+octet-stream",
"Upload-Offset": "5", "Upload-Offset": "5",
}, },
ReqBody: strings.NewReader("hello"), ReqBody: strings.NewReader("hello"),
@ -77,6 +78,7 @@ func TestPatch(t *testing.T) {
URL: "no", URL: "no",
ReqHeader: map[string]string{ ReqHeader: map[string]string{
"Tus-Resumable": "1.0.0", "Tus-Resumable": "1.0.0",
"Content-Type": "application/offset+octet-stream",
"Upload-Offset": "5", "Upload-Offset": "5",
}, },
Code: http.StatusNotFound, Code: http.StatusNotFound,
@ -88,6 +90,7 @@ func TestPatch(t *testing.T) {
URL: "yes", URL: "yes",
ReqHeader: map[string]string{ ReqHeader: map[string]string{
"Tus-Resumable": "1.0.0", "Tus-Resumable": "1.0.0",
"Content-Type": "application/offset+octet-stream",
"Upload-Offset": "4", "Upload-Offset": "4",
}, },
Code: http.StatusConflict, Code: http.StatusConflict,
@ -99,6 +102,7 @@ func TestPatch(t *testing.T) {
URL: "yes", URL: "yes",
ReqHeader: map[string]string{ ReqHeader: map[string]string{
"Tus-Resumable": "1.0.0", "Tus-Resumable": "1.0.0",
"Content-Type": "application/offset+octet-stream",
"Upload-Offset": "5", "Upload-Offset": "5",
}, },
ReqBody: strings.NewReader("hellothisismorethan15bytes"), ReqBody: strings.NewReader("hellothisismorethan15bytes"),
@ -194,6 +198,7 @@ func TestPatchOverflow(t *testing.T) {
URL: "yes", URL: "yes",
ReqHeader: map[string]string{ ReqHeader: map[string]string{
"Tus-Resumable": "1.0.0", "Tus-Resumable": "1.0.0",
"Content-Type": "application/offset+octet-stream",
"Upload-Offset": "5", "Upload-Offset": "5",
"Content-Length": "3", "Content-Length": "3",
}, },