last modified property handled through http header on PUT rather than PROPPATCH (#438)

This commit is contained in:
Michael Quigley 2024-01-16 13:54:01 -05:00
parent b50f665c93
commit 21df875716
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
7 changed files with 74 additions and 4 deletions

View File

@ -205,6 +205,30 @@ func (c *Client) Create(ctx context.Context, name string) (io.WriteCloser, error
return &fileWriter{pw, done}, nil
}
func (c *Client) CreateWithModTime(ctx context.Context, name string, modTime time.Time) (io.WriteCloser, error) {
pr, pw := io.Pipe()
req, err := c.ic.NewRequest(http.MethodPut, name, pr)
if err != nil {
pw.Close()
return nil, err
}
req.Header.Set("Zrok-Modtime", fmt.Sprintf("%d", modTime.Unix()))
done := make(chan error, 1)
go func() {
resp, err := c.ic.Do(req.WithContext(ctx))
if err != nil {
done <- err
return
}
resp.Body.Close()
done <- nil
}()
return &fileWriter{pw, done}, nil
}
func (c *Client) Touch(ctx context.Context, path string, mtime time.Time) error {
status, err := c.ic.Touch(ctx, path, mtime)
if err != nil {

View File

@ -8,12 +8,14 @@ package davServer
import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"io"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
)
@ -271,6 +273,22 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request) (status int,
}
_, copyErr := io.Copy(f, r.Body)
fi, statErr := f.Stat()
modTimes := r.Header["Zrok-Modtime"]
if len(modTimes) > 0 {
if modTimeV, err := strconv.ParseInt(modTimes[0], 10, 64); err == nil {
if v, ok := f.(*webdavFile); ok {
if err := v.updateModtime(reqPath, time.Unix(modTimeV, 0)); err != nil {
logrus.Warn(err)
}
} else {
logrus.Error("!ok")
}
} else {
logrus.Error(err)
}
}
closeErr := f.Close()
// TODO(rost): Returning 405 Method Not Allowed might not be appropriate.
if copyErr != nil {

View File

@ -131,6 +131,10 @@ func (t *FilesystemTarget) WriteStream(path string, stream io.Reader, mode os.Fi
return nil
}
func (t *FilesystemTarget) WriteStreamWithModTime(path string, stream io.Reader, mode os.FileMode, modTime time.Time) error {
return t.WriteStream(path, stream, mode)
}
func (t *FilesystemTarget) Move(src, dest string) error {
return os.Rename(filepath.Join(t.cfg.Root, src), filepath.Join(filepath.Dir(t.cfg.Root), dest))
}

View File

@ -20,6 +20,7 @@ type Target interface {
Mkdir(path string) error
ReadStream(path string) (io.ReadCloser, error)
WriteStream(path string, stream io.Reader, mode os.FileMode) error
WriteStreamWithModTime(path string, stream io.Reader, mode os.FileMode, modTime time.Time) error
Move(src, dest string) error
Rm(path string) error
SetModificationTime(path string, mtime time.Time) error

View File

@ -48,10 +48,7 @@ func OneWay(src, dst Target, sync bool) error {
if err != nil {
return err
}
if err := dst.WriteStream(copyPath.Path, ss, os.ModePerm); err != nil {
return err
}
if err := dst.SetModificationTime(copyPath.Path, copyPath.Modified); err != nil {
if err := dst.WriteStreamWithModTime(copyPath.Path, ss, os.ModePerm, copyPath.Modified); err != nil {
return err
}
}

View File

@ -118,6 +118,19 @@ func (t *WebDAVTarget) WriteStream(path string, rs io.Reader, _ os.FileMode) err
return nil
}
func (t *WebDAVTarget) WriteStreamWithModTime(path string, rs io.Reader, _ os.FileMode, modTime time.Time) error {
ws, err := t.dc.CreateWithModTime(context.Background(), filepath.Join(t.cfg.URL.Path, path), modTime)
if err != nil {
return err
}
defer func() { _ = ws.Close() }()
_, err = io.Copy(ws, rs)
if err != nil {
return err
}
return nil
}
func (t *WebDAVTarget) Move(src, dest string) error {
return t.dc.MoveAll(context.Background(), filepath.Join(t.cfg.URL.Path, src), dest, true)
}

View File

@ -130,6 +130,19 @@ func (t *ZrokTarget) WriteStream(path string, rs io.Reader, _ os.FileMode) error
return nil
}
func (t *ZrokTarget) WriteStreamWithModTime(path string, rs io.Reader, _ os.FileMode, modTime time.Time) error {
ws, err := t.dc.CreateWithModTime(context.Background(), filepath.Join(t.cfg.URL.Path, path), modTime)
if err != nil {
return err
}
defer func() { _ = ws.Close() }()
_, err = io.Copy(ws, rs)
if err != nil {
return err
}
return nil
}
func (t *ZrokTarget) Move(src, dest string) error {
return t.dc.MoveAll(context.Background(), filepath.Join(t.cfg.URL.Path, src), dest, true)
}