Skip to content

Commit

Permalink
Propagate Content-Length header from incoming PUT call to EOS PuT call
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesse Geens committed Oct 28, 2024
1 parent 287333f commit f04100c
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 19 deletions.
1 change: 1 addition & 0 deletions internal/http/services/datagateway/datagateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ func (s *svc) doPut(w http.ResponseWriter, r *http.Request) {

copyHeader(w.Header(), httpRes.Header)
if httpRes.StatusCode != http.StatusOK {
log.Warn().Int("StatusCode", httpRes.StatusCode).Msg("Non-OK Status Code when sending request to internal data server")
// swallow the body and set content-length to 0 to prevent reverse proxies from trying to read from it
w.Header().Set("Content-Length", "0")
w.WriteHeader(httpRes.StatusCode)
Expand Down
3 changes: 3 additions & 0 deletions internal/http/services/owncloud/ocdav/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ
httpReq.Header.Set(HeaderLockHolder, lockholder)
}

// Set Content-Length
httpReq.Header.Set(HeaderContentLength, strconv.FormatInt(length, 10))

// Propagate X-Disable-Versioning header
// Used to disable versioning for applications that do not expect this behaviour
// See reva#4855 for more info
Expand Down
2 changes: 1 addition & 1 deletion pkg/eosclient/eosbinary/eosbinary.go
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ func (c *Client) Read(ctx context.Context, auth eosclient.Authorization, path st
}

// Write writes a stream to the mgm.
func (c *Client) Write(ctx context.Context, auth eosclient.Authorization, path string, stream io.ReadCloser, app string, disableVersioning bool) error {
func (c *Client) Write(ctx context.Context, auth eosclient.Authorization, path string, stream io.ReadCloser, length int64, app string, disableVersioning bool) error {
fd, err := os.CreateTemp(c.opt.CacheDirectory, "eoswrite-")
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/eosclient/eosclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type EOSClient interface {
Rename(ctx context.Context, auth Authorization, oldPath, newPath string) error
List(ctx context.Context, auth Authorization, path string) ([]*FileInfo, error)
Read(ctx context.Context, auth Authorization, path string) (io.ReadCloser, error)
Write(ctx context.Context, auth Authorization, path string, stream io.ReadCloser, app string, disableVersioning bool) error
Write(ctx context.Context, auth Authorization, path string, stream io.ReadCloser, length int64, app string, disableVersioning bool) error
ListDeletedEntries(ctx context.Context, auth Authorization, maxentries int, from, to time.Time) ([]*DeletedEntry, error)
RestoreDeletedEntry(ctx context.Context, auth Authorization, key string) error
PurgeDeletedEntries(ctx context.Context, auth Authorization) error
Expand Down
4 changes: 1 addition & 3 deletions pkg/eosclient/eosgrpc/eosgrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1321,11 +1321,9 @@ func (c *Client) Read(ctx context.Context, auth eosclient.Authorization, path st

// Write writes a file to the mgm
// Somehow the same considerations as Read apply.
func (c *Client) Write(ctx context.Context, auth eosclient.Authorization, path string, stream io.ReadCloser, app string, disableVersioning bool) error {
func (c *Client) Write(ctx context.Context, auth eosclient.Authorization, path string, stream io.ReadCloser, length int64, app string, disableVersioning bool) error {
log := appctx.GetLogger(ctx)
log.Info().Str("func", "Write").Str("uid,gid", auth.Role.UID+","+auth.Role.GID).Str("path", path).Msg("")
var length int64
length = -1

u, err := getUser(ctx)
if err != nil {
Expand Down
12 changes: 0 additions & 12 deletions pkg/eosclient/eosgrpc/eoshttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,6 @@ func (c *EOSHTTPClient) PUTFile(ctx context.Context, remoteuser string, auth eos
base.RawQuery = queryValues.Encode()
finalurl := base.String()

if err != nil {
log.Error().Str("func", "PUTFile").Str("url", finalurl).Str("err", err.Error()).Msg("can't create request")
return err
}
req, err := http.NewRequestWithContext(ctx, http.MethodPut, finalurl, nil)
if err != nil {
log.Error().Str("func", "PUTFile").Str("url", finalurl).Str("err", err.Error()).Msg("can't create request")
Expand Down Expand Up @@ -426,14 +422,6 @@ func (c *EOSHTTPClient) PUTFile(ctx context.Context, remoteuser string, auth eos
log.Debug().Str("func", "PUTFile").Int64("Content-Length", length).Msg("setting header")
req.Header.Set("Content-Length", strconv.FormatInt(length, 10))
}
if err != nil {
log.Error().Str("func", "PUTFile").Str("url", loc.String()).Str("err", err.Error()).Msg("can't create redirected request")
return err
}
if length >= 0 {
log.Debug().Str("func", "PUTFile").Int64("Content-Length", length).Msg("setting header")
req.Header.Set("Content-Length", strconv.FormatInt(length, 10))
}

log.Debug().Str("func", "PUTFile").Str("location", loc.String()).Msg("redirection")
nredirs++
Expand Down
9 changes: 9 additions & 0 deletions pkg/rhttp/datatx/manager/simple/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package simple
import (
"context"
"net/http"
"strconv"

provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/internal/http/services/owncloud/ocdav"
Expand Down Expand Up @@ -88,6 +89,14 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) {
metadata["disableVersioning"] = disableVersioning
}

contentLength := r.Header.Get(ocdav.HeaderContentLength)

if _, err := strconv.ParseInt(contentLength, 10, 64); err == nil {
metadata[ocdav.HeaderContentLength] = contentLength
} else {
w.WriteHeader(http.StatusBadRequest)
}

err := fs.Upload(ctx, ref, r.Body, metadata)
switch v := err.(type) {
case nil:
Expand Down
9 changes: 8 additions & 1 deletion pkg/storage/utils/eosfs/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strconv"

provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/internal/http/services/owncloud/ocdav"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/storage/utils/chunking"
"github.com/pkg/errors"
Expand Down Expand Up @@ -93,7 +94,13 @@ func (fs *eosfs) Upload(ctx context.Context, ref *provider.Reference, r io.ReadC
disableVersioning = false
}

return fs.c.Write(ctx, auth, fn, r, app, disableVersioning)
contentLength := metadata[ocdav.HeaderContentLength]
len, err := strconv.ParseInt(contentLength, 10, 64)
if err != nil {
return errors.New("No content length specified in EOS upload, got: " + contentLength)
}

return fs.c.Write(ctx, auth, fn, r, len, app, disableVersioning)
}

func (fs *eosfs) InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) {
Expand Down
6 changes: 5 additions & 1 deletion tests/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import (
"os"
"path/filepath"
"runtime"
"strconv"

"github.com/pkg/errors"

gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/internal/http/services/datagateway"
"github.com/cs3org/reva/internal/http/services/owncloud/ocdav"
"github.com/cs3org/reva/pkg/httpclient"
"github.com/cs3org/reva/pkg/storage"
"github.com/studio-b12/gowebdav"
Expand Down Expand Up @@ -105,7 +107,9 @@ func Upload(ctx context.Context, fs storage.FS, ref *provider.Reference, content
return errors.New("simple upload method not available")
}
uploadRef := &provider.Reference{Path: "/" + uploadID}
err = fs.Upload(ctx, uploadRef, io.NopCloser(bytes.NewReader(content)), map[string]string{})
err = fs.Upload(ctx, uploadRef, io.NopCloser(bytes.NewReader(content)), map[string]string{
ocdav.HeaderUploadLength: strconv.FormatInt(int64(len(content)), 10),
})
return err
}

Expand Down

0 comments on commit f04100c

Please sign in to comment.