Skip to content

Commit

Permalink
refactor webdav tus post
Browse files Browse the repository at this point in the history
  • Loading branch information
David Christofas committed Jul 14, 2021
1 parent ffd17d3 commit fd3d412
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 31 deletions.
67 changes: 37 additions & 30 deletions internal/http/services/owncloud/ocdav/tus.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package ocdav

import (
"context"
"net/http"
"path"
"strconv"
Expand All @@ -31,15 +32,34 @@ import (
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/rhttp"
"github.com/cs3org/reva/pkg/utils"
"github.com/rs/zerolog"
tusd "github.com/tus/tusd/pkg/handler"
"go.opencensus.io/trace"
)

func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {
func (s *svc) handlePathTusPost(w http.ResponseWriter, r *http.Request, ns string) {
ctx := r.Context()
ctx, span := trace.StartSpan(ctx, "tus-post")
defer span.End()

// read filename from metadata
meta := tusd.ParseMetadataHeader(r.Header.Get(HeaderUploadMetadata))
if meta["filename"] == "" {
w.WriteHeader(http.StatusPreconditionFailed)
return
}

// append filename to current dir
fn := path.Join(ns, r.URL.Path, meta["filename"])

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
// check tus headers?

ref := &provider.Reference{Path: fn}
s.handleTusPost(ctx, w, r, meta, ref, sublog)
}

func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http.Request, meta map[string]string, ref *provider.Reference, log zerolog.Logger) {
w.Header().Add(HeaderAccessControlAllowHeaders, strings.Join([]string{HeaderTusResumable, HeaderUploadLength, HeaderUploadMetadata, HeaderIfMatch}, ", "))
w.Header().Add(HeaderAccessControlExposeHeaders, strings.Join([]string{HeaderTusResumable, HeaderLocation}, ", "))

Expand All @@ -62,45 +82,32 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {

// TODO check Expect: 100-continue

// read filename from metadata
meta := tusd.ParseMetadataHeader(r.Header.Get(HeaderUploadMetadata))
if meta["filename"] == "" {
w.WriteHeader(http.StatusPreconditionFailed)
return
}

// append filename to current dir
fn := path.Join(ns, r.URL.Path, meta["filename"])

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
// check tus headers?

// check if destination exists or is a file
client, err := s.getClient()
if err != nil {
sublog.Error().Err(err).Msg("error getting grpc client")
log.Error().Err(err).Msg("error getting grpc client")
w.WriteHeader(http.StatusInternalServerError)
return
}

sReq := &provider.StatRequest{
Ref: &provider.Reference{Path: fn},
Ref: ref,
}
sRes, err := client.Stat(ctx, sReq)
if err != nil {
sublog.Error().Err(err).Msg("error sending grpc stat request")
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}

if sRes.Status.Code != rpc.Code_CODE_OK && sRes.Status.Code != rpc.Code_CODE_NOT_FOUND {
HandleErrorStatus(&sublog, w, sRes.Status)
HandleErrorStatus(&log, w, sRes.Status)
return
}

info := sRes.Info
if info != nil && info.Type != provider.ResourceType_RESOURCE_TYPE_FILE {
sublog.Warn().Msg("resource is not a file")
log.Warn().Msg("resource is not a file")
w.WriteHeader(http.StatusConflict)
return
}
Expand All @@ -110,7 +117,7 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {
serverETag := info.Etag
if clientETag != "" {
if clientETag != serverETag {
sublog.Warn().Str("client-etag", clientETag).Str("server-etag", serverETag).Msg("etags mismatch")
log.Warn().Str("client-etag", clientETag).Str("server-etag", serverETag).Msg("etags mismatch")
w.WriteHeader(http.StatusPreconditionFailed)
return
}
Expand All @@ -134,21 +141,21 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {

// initiateUpload
uReq := &provider.InitiateFileUploadRequest{
Ref: &provider.Reference{Path: fn},
Ref: ref,
Opaque: &typespb.Opaque{
Map: opaqueMap,
},
}

uRes, err := client.InitiateFileUpload(ctx, uReq)
if err != nil {
sublog.Error().Err(err).Msg("error initiating file upload")
log.Error().Err(err).Msg("error initiating file upload")
w.WriteHeader(http.StatusInternalServerError)
return
}

if uRes.Status.Code != rpc.Code_CODE_OK {
HandleErrorStatus(&sublog, w, uRes.Status)
HandleErrorStatus(&log, w, uRes.Status)
return
}

Expand Down Expand Up @@ -176,7 +183,7 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {

length, err := strconv.ParseInt(r.Header.Get(HeaderContentLength), 10, 64)
if err != nil {
sublog.Debug().Err(err).Msg("wrong request")
log.Debug().Err(err).Msg("wrong request")
w.WriteHeader(http.StatusBadRequest)
return
}
Expand All @@ -186,7 +193,7 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {
if length != 0 {
httpReq, err := rhttp.NewRequest(ctx, http.MethodPatch, ep, r.Body)
if err != nil {
sublog.Debug().Err(err).Msg("wrong request")
log.Debug().Err(err).Msg("wrong request")
w.WriteHeader(http.StatusInternalServerError)
return
}
Expand All @@ -202,7 +209,7 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {

httpRes, err = s.client.Do(httpReq)
if err != nil {
sublog.Error().Err(err).Msg("error doing GET request to data service")
log.Error().Err(err).Msg("error doing GET request to data service")
w.WriteHeader(http.StatusInternalServerError)
return
}
Expand All @@ -215,27 +222,27 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {
return
}
} else {
sublog.Debug().Msg("Skipping sending a Patch request as body is empty")
log.Debug().Msg("Skipping sending a Patch request as body is empty")
}

// check if upload was fully completed
if length == 0 || httpRes.Header.Get(HeaderUploadOffset) == r.Header.Get(HeaderUploadLength) {
// get uploaded file metadata
sRes, err := client.Stat(ctx, sReq)
if err != nil {
sublog.Error().Err(err).Msg("error sending grpc stat request")
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}

if sRes.Status.Code != rpc.Code_CODE_OK && sRes.Status.Code != rpc.Code_CODE_NOT_FOUND {
HandleErrorStatus(&sublog, w, sRes.Status)
HandleErrorStatus(&log, w, sRes.Status)
return
}

info := sRes.Info
if info == nil {
sublog.Error().Msg("No info found for uploaded file")
log.Error().Msg("No info found for uploaded file")
w.WriteHeader(http.StatusInternalServerError)
return
}
Expand Down
2 changes: 1 addition & 1 deletion internal/http/services/owncloud/ocdav/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (h *WebDavHandler) Handler(s *svc) http.Handler {
case http.MethodPut:
s.handlePathPut(w, r, ns)
case http.MethodPost:
s.handleTusPost(w, r, ns)
s.handlePathTusPost(w, r, ns)
case http.MethodOptions:
s.handleOptions(w, r, ns)
case http.MethodHead:
Expand Down

0 comments on commit fd3d412

Please sign in to comment.