Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal WebDAV client incompatible with rclone webdav server #858

Closed
projectgus opened this issue Jan 27, 2025 · 2 comments
Closed

Internal WebDAV client incompatible with rclone webdav server #858

projectgus opened this issue Jan 27, 2025 · 2 comments

Comments

@projectgus
Copy link

projectgus commented Jan 27, 2025

I have an rclone WebDAV server (rclone serve webdav ...) running behind an HTTPS reverse proxy. This server works with the DavX5 client but appears to fail with the internal Seedvault WebDAV client.

Steps to reproduce

Steps to reproduce are a bit fiddly because you need a trusted HTTPS front-end in front of the rclone server. I can privately provide a server for testing if that's useful.

After setting up the server and entering any auth details, then tapping "Use WebDAV Cloud" there is an immediate HTTP 405 (Method Not Allowed) error shown. Logcat shows:

01-28 09:25:02.387 21197 21240 D a.g.s.c.b.w.WebDavBackend: [DefaultDispatcher-worker-6] test() = [1, 2] Response{protocol=h2, code=200, message=, url=https://HOST/my/webdav/}
01-28 09:25:02.396 21197 21240 E WebDavHandler: Error testing WebDAV config at https://HOST/my/webdav/
01-28 09:25:02.396 21197 21240 E WebDavHandler: at.bitfire.dav4jvm.exception.HttpException: HTTP 405 
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at at.bitfire.dav4jvm.DavResource.checkStatus(DavResource.kt:650)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at at.bitfire.dav4jvm.DavResource.checkStatus(DavResource.kt:624)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at at.bitfire.dav4jvm.DavResource.head(DavResource.kt:296)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at app.grapheneos.seedvault.core.backends.webdav.WebDavHelperKt.ensureFoldersExist(WebDavHelper.kt:92)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at app.grapheneos.seedvault.core.backends.webdav.WebDavBackend.test(WebDavBackend.kt:101)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at com.stevesoltys.seedvault.backend.webdav.WebDavHandler.onConfigReceived(WebDavHandler.kt:59)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at com.stevesoltys.seedvault.ui.storage.StorageViewModel$onWebDavConfigReceived$1.invokeSuspend(StorageViewModel.kt:101)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
01-28 09:25:02.396 21197 21240 E WebDavHandler:         at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)

rclone debug log shows two requests:

Jan 28 10:21:10 host webdav[879352]: 2025/01/27 23:21:10 INFO  : /my/webdav/: OPTIONS from 127.0.0.1:58044
Jan 28 10:21:10 host webdav[879352]: 2025/01/27 23:21:10 DEBUG : /.SeedVaultAndroidBackup: OpenFile: flags=O_RDONLY, perm=----------
Jan 28 10:21:10 host webdav[879352]: 2025/01/27 23:21:10 DEBUG : /.SeedVaultAndroidBackup: >OpenFile: fd=.SeedVaultAndroidBackup/ (r), err=<nil>
Jan 28 10:21:10 host webdav[879352]: 2025/01/27 23:21:10 INFO  : /my/webdav/.SeedVaultAndroidBackup: HEAD from 127.0.0.1:58044

Also visible in the the reverse proxy log which shows the OPTIONS request succeeds and then the HEAD fails:

Jan 28 09:25:01 host traefik[513415]: 192.168.66.182 - - [27/Jan/2025:22:25:01 +0000] "OPTIONS /my/webdav/ HTTP/2.0" 200 0 "-" "-" 4914 "webdav@file" "http://127.0.0.1:8888/" 0ms
Jan 28 09:25:01 host traefik[513415]: 192.168.66.182 - - [27/Jan/2025:22:25:01 +0000] "HEAD /my/webdav/.SeedVaultAndroidBackup HTTP/2.0" 405 0 "-" "-" 4915 "webdav@file" "http://127.0.0.1:8888/" 4ms

Possible root cause

I believe the problem is that the collection URL generated in the ensureFoldersExist helper function (in this case /my/webdav/.SeedVaultAndroidBackup) is missing a trailing slash. RFC4198 says WebDAV servers can optionally handle a request formatted this way:

There is a standing convention that when a collection is referred to
by its name without a trailing slash, the server MAY handle the
request as if the trailing slash were present.
[...]
In general, clients SHOULD use the trailing slash form of
collection names.

However, Rclone instead uses the presence of a trailing slash as an indication that a request is for a collection when handling GET and HEAD: https://github.com/rclone/rclone/blob/master/cmd/serve/webdav/webdav.go#L332

I can see the behaviour locally with curl, running mkdir testdir; rclone -vv serve webdav $PWD

❯ curl --head http://localhost:8080/testdir
HTTP/1.1 405 Method Not Allowed
Accept-Ranges: bytes
Server: rclone/v1.68.2
Date: Mon, 27 Jan 2025 23:55:22 GMT
Content-Length: 18
Content-Type: text/plain; charset=utf-8

❯ curl --head http://localhost:8080/testdir/
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 13625
Server: rclone/v1.68.2
Date: Mon, 27 Jan 2025 23:55:26 GMT
Content-Type: text/html; charset=utf-8

My reading is that what Rclone does is technically RFC compliant, although also uncommon.

This could also be considered as a bug in the dav4jvm DavCollection class (which uses the supplied collection URL verbatim, where it arguably could check and append the trailing slash). If so then I'm happy to open an issue there, instead.

@grote
Copy link
Collaborator

grote commented Jan 29, 2025

Thanks for the report. Are you able to run your own builds of Seedvault? If so, please test if this is fixed with #857 or 1a0a94a specifically.

Otherwise, I could test with a test account for the server you could mail to t at grobox dot de.

@grote
Copy link
Collaborator

grote commented Jan 29, 2025

potential duplicate of #825

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants