mirror of
https://github.com/1f349/go-webdav.git
synced 2024-12-23 00:34:23 +00:00
webdav: add context to FileSystem
This commit is contained in:
parent
379a418130
commit
d033e09835
21
fs_local.go
21
fs_local.go
@ -1,6 +1,7 @@
|
|||||||
package webdav
|
package webdav
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
@ -15,6 +16,8 @@ import (
|
|||||||
|
|
||||||
type LocalFileSystem string
|
type LocalFileSystem string
|
||||||
|
|
||||||
|
var _ FileSystem = LocalFileSystem("")
|
||||||
|
|
||||||
func (fs LocalFileSystem) localPath(name string) (string, error) {
|
func (fs LocalFileSystem) localPath(name string) (string, error) {
|
||||||
if (filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0) || strings.Contains(name, "\x00") {
|
if (filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0) || strings.Contains(name, "\x00") {
|
||||||
return "", internal.HTTPErrorf(http.StatusBadRequest, "webdav: invalid character in path")
|
return "", internal.HTTPErrorf(http.StatusBadRequest, "webdav: invalid character in path")
|
||||||
@ -34,7 +37,7 @@ func (fs LocalFileSystem) externalPath(name string) (string, error) {
|
|||||||
return "/" + filepath.ToSlash(rel), nil
|
return "/" + filepath.ToSlash(rel), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) Open(name string) (io.ReadCloser, error) {
|
func (fs LocalFileSystem) Open(ctx context.Context, name string) (io.ReadCloser, error) {
|
||||||
p, err := fs.localPath(name)
|
p, err := fs.localPath(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -59,7 +62,7 @@ func fileInfoFromOS(p string, fi os.FileInfo) *FileInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) Stat(name string) (*FileInfo, error) {
|
func (fs LocalFileSystem) Stat(ctx context.Context, name string) (*FileInfo, error) {
|
||||||
p, err := fs.localPath(name)
|
p, err := fs.localPath(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -71,7 +74,7 @@ func (fs LocalFileSystem) Stat(name string) (*FileInfo, error) {
|
|||||||
return fileInfoFromOS(name, fi), nil
|
return fileInfoFromOS(name, fi), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) Readdir(name string, recursive bool) ([]FileInfo, error) {
|
func (fs LocalFileSystem) ReadDir(ctx context.Context, name string, recursive bool) ([]FileInfo, error) {
|
||||||
path, err := fs.localPath(name)
|
path, err := fs.localPath(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -98,7 +101,7 @@ func (fs LocalFileSystem) Readdir(name string, recursive bool) ([]FileInfo, erro
|
|||||||
return l, err
|
return l, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) Create(name string) (io.WriteCloser, error) {
|
func (fs LocalFileSystem) Create(ctx context.Context, name string) (io.WriteCloser, error) {
|
||||||
p, err := fs.localPath(name)
|
p, err := fs.localPath(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -106,7 +109,7 @@ func (fs LocalFileSystem) Create(name string) (io.WriteCloser, error) {
|
|||||||
return os.Create(p)
|
return os.Create(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) RemoveAll(name string) error {
|
func (fs LocalFileSystem) RemoveAll(ctx context.Context, name string) error {
|
||||||
p, err := fs.localPath(name)
|
p, err := fs.localPath(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -121,7 +124,7 @@ func (fs LocalFileSystem) RemoveAll(name string) error {
|
|||||||
return os.RemoveAll(p)
|
return os.RemoveAll(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) Mkdir(name string) error {
|
func (fs LocalFileSystem) Mkdir(ctx context.Context, name string) error {
|
||||||
p, err := fs.localPath(name)
|
p, err := fs.localPath(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -150,7 +153,7 @@ func copyRegularFile(src, dst string, perm os.FileMode) error {
|
|||||||
return dstFile.Close()
|
return dstFile.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) Copy(src, dst string, recursive, overwrite bool) (created bool, err error) {
|
func (fs LocalFileSystem) Copy(ctx context.Context, src, dst string, recursive, overwrite bool) (created bool, err error) {
|
||||||
srcPath, err := fs.localPath(src)
|
srcPath, err := fs.localPath(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -210,7 +213,7 @@ func (fs LocalFileSystem) Copy(src, dst string, recursive, overwrite bool) (crea
|
|||||||
return created, nil
|
return created, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs LocalFileSystem) MoveAll(src, dst string, overwrite bool) (created bool, err error) {
|
func (fs LocalFileSystem) MoveAll(ctx context.Context, src, dst string, overwrite bool) (created bool, err error) {
|
||||||
srcPath, err := fs.localPath(src)
|
srcPath, err := fs.localPath(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -240,5 +243,3 @@ func (fs LocalFileSystem) MoveAll(src, dst string, overwrite bool) (created bool
|
|||||||
|
|
||||||
return created, nil
|
return created, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ FileSystem = LocalFileSystem("")
|
|
||||||
|
36
server.go
36
server.go
@ -14,14 +14,14 @@ import (
|
|||||||
|
|
||||||
// FileSystem is a WebDAV server backend.
|
// FileSystem is a WebDAV server backend.
|
||||||
type FileSystem interface {
|
type FileSystem interface {
|
||||||
Open(name string) (io.ReadCloser, error)
|
Open(ctx context.Context, name string) (io.ReadCloser, error)
|
||||||
Stat(name string) (*FileInfo, error)
|
Stat(ctx context.Context, name string) (*FileInfo, error)
|
||||||
Readdir(name string, recursive bool) ([]FileInfo, error)
|
ReadDir(ctx context.Context, name string, recursive bool) ([]FileInfo, error)
|
||||||
Create(name string) (io.WriteCloser, error)
|
Create(ctx context.Context, name string) (io.WriteCloser, error)
|
||||||
RemoveAll(name string) error
|
RemoveAll(ctx context.Context, name string) error
|
||||||
Mkdir(name string) error
|
Mkdir(ctx context.Context, name string) error
|
||||||
Copy(name, dest string, recursive, overwrite bool) (created bool, err error)
|
Copy(ctx context.Context, name, dest string, recursive, overwrite bool) (created bool, err error)
|
||||||
MoveAll(name, dest string, overwrite bool) (created bool, err error)
|
MoveAll(ctx context.Context, name, dest string, overwrite bool) (created bool, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler handles WebDAV HTTP requests. It can be used to create a WebDAV
|
// Handler handles WebDAV HTTP requests. It can be used to create a WebDAV
|
||||||
@ -56,7 +56,7 @@ type backend struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Options(r *http.Request) (caps []string, allow []string, err error) {
|
func (b *backend) Options(r *http.Request) (caps []string, allow []string, err error) {
|
||||||
fi, err := b.FileSystem.Stat(r.URL.Path)
|
fi, err := b.FileSystem.Stat(r.Context(), r.URL.Path)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, []string{http.MethodOptions, http.MethodPut, "MKCOL"}, nil
|
return nil, []string{http.MethodOptions, http.MethodPut, "MKCOL"}, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@ -79,7 +79,7 @@ func (b *backend) Options(r *http.Request) (caps []string, allow []string, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) HeadGet(w http.ResponseWriter, r *http.Request) error {
|
func (b *backend) HeadGet(w http.ResponseWriter, r *http.Request) error {
|
||||||
fi, err := b.FileSystem.Stat(r.URL.Path)
|
fi, err := b.FileSystem.Stat(r.Context(), r.URL.Path)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return &internal.HTTPError{Code: http.StatusNotFound, Err: err}
|
return &internal.HTTPError{Code: http.StatusNotFound, Err: err}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@ -89,7 +89,7 @@ func (b *backend) HeadGet(w http.ResponseWriter, r *http.Request) error {
|
|||||||
return &internal.HTTPError{Code: http.StatusMethodNotAllowed}
|
return &internal.HTTPError{Code: http.StatusMethodNotAllowed}
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := b.FileSystem.Open(r.URL.Path)
|
f, err := b.FileSystem.Open(r.Context(), r.URL.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ func (b *backend) HeadGet(w http.ResponseWriter, r *http.Request) error {
|
|||||||
func (b *backend) PropFind(r *http.Request, propfind *internal.PropFind, depth internal.Depth) (*internal.MultiStatus, error) {
|
func (b *backend) PropFind(r *http.Request, propfind *internal.PropFind, depth internal.Depth) (*internal.MultiStatus, error) {
|
||||||
// TODO: use partial error Response on error
|
// TODO: use partial error Response on error
|
||||||
|
|
||||||
fi, err := b.FileSystem.Stat(r.URL.Path)
|
fi, err := b.FileSystem.Stat(r.Context(), r.URL.Path)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, &internal.HTTPError{Code: http.StatusNotFound, Err: err}
|
return nil, &internal.HTTPError{Code: http.StatusNotFound, Err: err}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@ -129,7 +129,7 @@ func (b *backend) PropFind(r *http.Request, propfind *internal.PropFind, depth i
|
|||||||
|
|
||||||
var resps []internal.Response
|
var resps []internal.Response
|
||||||
if depth != internal.DepthZero && fi.IsDir {
|
if depth != internal.DepthZero && fi.IsDir {
|
||||||
children, err := b.FileSystem.Readdir(r.URL.Path, depth == internal.DepthInfinity)
|
children, err := b.FileSystem.ReadDir(r.Context(), r.URL.Path, depth == internal.DepthInfinity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ func (b *backend) PropPatch(r *http.Request, update *internal.PropertyUpdate) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Put(r *http.Request) (*internal.Href, error) {
|
func (b *backend) Put(r *http.Request) (*internal.Href, error) {
|
||||||
wc, err := b.FileSystem.Create(r.URL.Path)
|
wc, err := b.FileSystem.Create(r.Context(), r.URL.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ func (b *backend) Put(r *http.Request) (*internal.Href, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Delete(r *http.Request) error {
|
func (b *backend) Delete(r *http.Request) error {
|
||||||
err := b.FileSystem.RemoveAll(r.URL.Path)
|
err := b.FileSystem.RemoveAll(r.Context(), r.URL.Path)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return &internal.HTTPError{Code: http.StatusNotFound, Err: err}
|
return &internal.HTTPError{Code: http.StatusNotFound, Err: err}
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ func (b *backend) Mkcol(r *http.Request) error {
|
|||||||
if r.Header.Get("Content-Type") != "" {
|
if r.Header.Get("Content-Type") != "" {
|
||||||
return internal.HTTPErrorf(http.StatusUnsupportedMediaType, "webdav: request body not supported in MKCOL request")
|
return internal.HTTPErrorf(http.StatusUnsupportedMediaType, "webdav: request body not supported in MKCOL request")
|
||||||
}
|
}
|
||||||
err := b.FileSystem.Mkdir(r.URL.Path)
|
err := b.FileSystem.Mkdir(r.Context(), r.URL.Path)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return &internal.HTTPError{Code: http.StatusConflict, Err: err}
|
return &internal.HTTPError{Code: http.StatusConflict, Err: err}
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ func (b *backend) Mkcol(r *http.Request) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Copy(r *http.Request, dest *internal.Href, recursive, overwrite bool) (created bool, err error) {
|
func (b *backend) Copy(r *http.Request, dest *internal.Href, recursive, overwrite bool) (created bool, err error) {
|
||||||
created, err = b.FileSystem.Copy(r.URL.Path, dest.Path, recursive, overwrite)
|
created, err = b.FileSystem.Copy(r.Context(), r.URL.Path, dest.Path, recursive, overwrite)
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return false, &internal.HTTPError{http.StatusPreconditionFailed, err}
|
return false, &internal.HTTPError{http.StatusPreconditionFailed, err}
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ func (b *backend) Copy(r *http.Request, dest *internal.Href, recursive, overwrit
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Move(r *http.Request, dest *internal.Href, overwrite bool) (created bool, err error) {
|
func (b *backend) Move(r *http.Request, dest *internal.Href, overwrite bool) (created bool, err error) {
|
||||||
created, err = b.FileSystem.MoveAll(r.URL.Path, dest.Path, overwrite)
|
created, err = b.FileSystem.MoveAll(r.Context(), r.URL.Path, dest.Path, overwrite)
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return false, &internal.HTTPError{http.StatusPreconditionFailed, err}
|
return false, &internal.HTTPError{http.StatusPreconditionFailed, err}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user