the internal HTTP client of go-webdav will send the request with the URL https://uXXXX.your-storagebox.de/asset1 and the method PROPFIND, but then the server will respond with HTTP status code 302 and a Location: https://uXXXX.your-storagebox.de/asset1/ header. This really shouldn't be an issue since the Golang HTTP client follows any redirects by default (I actually couldn't debug what I have just stated without disabling the automatic redirections following first). However the request made after the redirect loses its request method (PROPFIND) and always gets changed to a GET request, and here all the issues start (since as I said in the start, the Hetzner WebDAV server will respond with HTML if the request method isn't one of the WebDAV request verbs)
I don't really know why the HTTP client doesn't follow the redirections with the same request method of the original request, but I managed to solve it by creating my own Transport like that:
type webdavTransport struct {
username string
password string
}
func (t *webdavTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.SetBasicAuth(t.username, t.password)
var resp *http.Response
var err error
resp, err = http.DefaultTransport.RoundTrip(req)
if err == nil {
if resp.StatusCode == 301 || resp.StatusCode == 302 {
newURL, _ := resp.Location()
reqNew, _ := http.NewRequest(req.Method, newURL.String(), req.Body)
reqNew.Header = req.Header
respNew, errNew := http.DefaultTransport.RoundTrip(reqNew)
resp = respNew
err = errNew
}
}
return resp, err
}
func FixedWebdavClientWithAuth(url, username, password string) (*webdav.Client, error) {
client := &http.Client{
Transport: &webdavTransport{
username: username,
password: password,
},
// Disable any redirections following since we'll manually handle this in the transport's RoundTripper
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
return webdav.NewClient(client, url)
}
now using
webdav, err := FixedWebdavClientWithAuth("https://uXXXX.your-storagebox.de", "[redacted]", "[redacted]")
if err != nil {
fmt.Println("unable to access")
}
data, err := webdav.Readdir("/asset1", false)
if err != nil {
fmt.Println(err)
fmt.Println("unable to access")
}
fmt.Println(data)
solves the issue and data gets printed successfully with no issues
Hello,
I tried using your WebDAV client to access my Hetzner storage box through their WebDAV server (pretty sure they use Apache as their WebDAV server)
First off, I noticed how their WebDAV differs than most of the WebDAV servers I have used before:
So what's the issue?
If we perform a
Readdir
(for example) query on the Hetzner WebDAV server like that:the internal HTTP client of
go-webdav
will send the request with the URLhttps://uXXXX.your-storagebox.de/asset1
and the methodPROPFIND
, but then the server will respond with HTTP status code302
and aLocation: https://uXXXX.your-storagebox.de/asset1/
header. This really shouldn't be an issue since the Golang HTTP client follows any redirects by default (I actually couldn't debug what I have just stated without disabling the automatic redirections following first). However the request made after the redirect loses its request method (PROPFIND
) and always gets changed to aGET
request, and here all the issues start (since as I said in the start, the Hetzner WebDAV server will respond with HTML if the request method isn't one of the WebDAV request verbs)I don't really know why the HTTP client doesn't follow the redirections with the same request method of the original request, but I managed to solve it by creating my own Transport like that:
now using
solves the issue and
data
gets printed successfully with no issues