Skip to content

Commit cf240b6

Browse files
bbockelmncw
authored andcommitted
webdav: permit redirects on PROPFIND for metadata
The WebDAV implementation already permits redirects on PROPFIND for listing paths in the `listAll` method but does not permit this for metadata in `readMetaDataForPath`. This results in a strange experience for endpoints that heavily use redirects - ``` rclone lsl endpoint: ``` functions and lists `hello_world.txt` in its output but ``` rclone lsl endpoint:hello_world.txt ``` Fails with a HTTP 307. The git history for this setting indicates this was done to avoid an issue where redirects cause a verb change to GET in the Go HTTP client; it does not appear to be problematic with HTTP 307. To fix, a new `CheckRedirect` function is added in the `rest` library to force the client to use the same verb across redirects, forcing this for the PROPFIND case.
1 parent 6159ea9 commit cf240b6

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

backend/webdav/webdav.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ func (f *Fs) readMetaDataForPath(ctx context.Context, path string, depth string)
348348
ExtraHeaders: map[string]string{
349349
"Depth": depth,
350350
},
351-
NoRedirect: true,
351+
CheckRedirect: rest.PreserveMethodRedirectFn,
352352
}
353353
if f.hasOCMD5 || f.hasOCSHA1 {
354354
opts.Body = bytes.NewBuffer(owncloudProps)

lib/rest/rest.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,22 @@ func ClientWithNoRedirects(c *http.Client) *http.Client {
215215
return &clientCopy
216216
}
217217

218+
// PreserveMethodRedirectFn is a CheckRedirect function that
219+
// preserves the original HTTP method on redirects.
220+
//
221+
// By default Go's http.Client changes the method to GET on 301, 302,
222+
// and 303 redirects. This function overrides that behaviour so the
223+
// original method (e.g. PROPFIND being preserved across a 307) is kept.
224+
func PreserveMethodRedirectFn(req *http.Request, via []*http.Request) error {
225+
if len(via) >= 10 {
226+
return errors.New("stopped after 10 redirects")
227+
}
228+
if len(via) > 0 {
229+
req.Method = via[0].Method
230+
}
231+
return nil
232+
}
233+
218234
// Do calls the internal http.Client.Do method
219235
func (api *Client) Do(req *http.Request) (*http.Response, error) {
220236
return api.c.Do(req)

0 commit comments

Comments
 (0)