Auto-vivify WebDAV prefix directories
Previously, specifying a WebDAV prefix that did not already exist was an
error.  This has been fixed, so that the prefix directories are
automatically created on "connect".  This allows the `webdav` plugin ti
behave more like the `s3` plugin.
@@ -201,7 +201,36 @@ func configure(endpoint plugin.ShieldEndpoint) (WebDAV, error) {
Username: username,
Password: password,
SkipVerify: skip,
- }, nil
+ }.setup()
+}
+
+func (dav WebDAV) setup() (WebDAV, error) {
+ /* create the prefix, if there is one */
+ u, err := url.Parse(dav.URL)
+ if err != nil {
+ return dav, fmt.Errorf("unable to parse WebDAV URL '%s': %s", dav.URL, err)
+ }
+
+ parts := strings.Split(strings.TrimPrefix(u.Path, "/"), "/")
+ for i := 1; i <= len(parts); i++ {
+ dir := strings.Join(parts[:i], "/")
+ plugin.Infof("creating prefix directory '%s'", dir)
+ u.Path = dir + "/"
+ fmt.Fprintf(os.Stderr, "requesting MKCOL %s\n", u)
+ req, err := http.NewRequest("MKCOL", u.String(), nil)
+ if err != nil {
+ return dav, fmt.Errorf("unable to create WebDAV prefix directory %s: %s", dir, err)
+ }
+ res, err := dav.request(req)
+ if err != nil {
+ return dav, fmt.Errorf("unable to create WebDAV prefix directory %s: %s", dir, err)
+ }
+ if res.StatusCode != 201 && res.StatusCode != 405 {
+ return dav, fmt.Errorf("unable to create WebDAV prefix directory %s: got an HTTP %d response from the WebDAV server", dir, res.StatusCode)
+ }
+ }
+
+ return dav, nil
}
func (dav WebDAV) generate() string {
@@ -213,19 +242,7 @@ func (dav WebDAV) generate() string {
return strings.Replace(path, "//", "/", -1)
}
-func (dav WebDAV) do(method, path string, in io.Reader) (*http.Response, error) {
- u, err := url.Parse(dav.URL)
- if err != nil {
- return nil, err
- }
- u.Path = fmt.Sprintf("%s/%s", strings.TrimSuffix(u.Path, "/"), path)
- fmt.Fprintf(os.Stderr, "requesting %s %s\n", method, u)
-
- req, err := http.NewRequest(method, u.String(), in)
- if err != nil {
- return nil, err
- }
-
+func (dav WebDAV) request(req *http.Request) (*http.Response, error) {
if dav.Username != "" {
req.SetBasicAuth(dav.Username, dav.Password)
}
@@ -242,6 +259,22 @@ func (dav WebDAV) do(method, path string, in io.Reader) (*http.Response, error)
return dav.c.Do(req)
}
+func (dav WebDAV) do(method, path string, in io.Reader) (*http.Response, error) {
+ u, err := url.Parse(dav.URL)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = fmt.Sprintf("%s/%s", strings.TrimSuffix(u.Path, "/"), path)
+ fmt.Fprintf(os.Stderr, "requesting %s %s\n", method, u)
+
+ req, err := http.NewRequest(method, u.String(), in)
+ if err != nil {
+ return nil, err
+ }
+
+ return dav.request(req)
+}
+
func (dav WebDAV) Put(path string, in io.Reader) (int64, error) {
fmt.Fprintf(os.Stderr, "storing archive at '%s'\n", path)
