Merge pull request #27 from vayam/master
Protocol Conformance + Bug fixes
This commit is contained in:
commit
b6b65c5dee
31
handler.go
31
handler.go
|
@ -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
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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",
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue