diff --git a/carddav/server.go b/carddav/server.go index 90e6f1b..e4bfaaa 100644 --- a/carddav/server.go +++ b/carddav/server.go @@ -268,3 +268,7 @@ func (b *backend) Put(r *http.Request) error { func (b *backend) Delete(r *http.Request) error { panic("TODO") } + +func (b *backend) Mkcol(r *http.Request) error { + return internal.HTTPErrorf(http.StatusForbidden, "carddav: address book creation unsupported") +} diff --git a/fs_local.go b/fs_local.go index 46b3983..983cf13 100644 --- a/fs_local.go +++ b/fs_local.go @@ -76,4 +76,12 @@ func (fs LocalFileSystem) RemoveAll(name string) error { return os.RemoveAll(p) } +func (fs LocalFileSystem) Mkdir(name string) error { + p, err := fs.path(name) + if err != nil { + return err + } + return os.Mkdir(p, 0755) +} + var _ FileSystem = LocalFileSystem("") diff --git a/internal/server.go b/internal/server.go index 2b37d91..04d25d9 100644 --- a/internal/server.go +++ b/internal/server.go @@ -79,6 +79,7 @@ type Backend interface { Propfind(r *http.Request, pf *Propfind, depth Depth) (*Multistatus, error) Put(r *http.Request) error Delete(r *http.Request) error + Mkcol(r *http.Request) error } type Handler struct { @@ -111,6 +112,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } case "PROPFIND": err = h.handlePropfind(w, r) + case "MKCOL": + err = h.Backend.Mkcol(r) + if err == nil { + w.WriteHeader(http.StatusCreated) + } default: err = HTTPErrorf(http.StatusMethodNotAllowed, "webdav: unsupported method") } diff --git a/server.go b/server.go index 1b4d80d..5506552 100644 --- a/server.go +++ b/server.go @@ -25,6 +25,7 @@ type FileSystem interface { Readdir(name string) ([]os.FileInfo, error) Create(name string) (io.WriteCloser, error) RemoveAll(name string) error + Mkdir(name string) error } // Handler handles WebDAV HTTP requests. It can be used to create a WebDAV @@ -58,7 +59,12 @@ func (b *backend) Options(r *http.Request) ([]string, error) { } if fi.IsDir() { - return []string{http.MethodOptions, http.MethodDelete, "PROPFIND"}, nil + return []string{ + http.MethodOptions, + http.MethodDelete, + "PROPFIND", + "MKCOL", + }, nil } else { return []string{ http.MethodOptions, @@ -192,3 +198,14 @@ func (b *backend) Delete(r *http.Request) error { } return err } + +func (b *backend) Mkcol(r *http.Request) error { + if r.Header.Get("Content-Type") != "" { + return internal.HTTPErrorf(http.StatusUnsupportedMediaType, "webdav: request body not supported in MKCOL request") + } + err := b.FileSystem.Mkdir(r.URL.Path) + if os.IsNotExist(err) { + return &internal.HTTPError{Code: http.StatusConflict, Err: err} + } + return err +}