bitfireAT / davx5-ose

DAVx⁵ is an open-source CalDAV/CardDAV suite and sync app for Android. You can also access your online files (WebDAV) with it.
https://www.davx5.com
GNU General Public License v3.0
1.6k stars 78 forks source link

[WebDAV] ETag cache is not invalidated by 412 response to GET w/ If-Match #1150

Open vuori opened 1 day ago

vuori commented 1 day ago

Problem scope

App version

Android version and device/firmware type

Android 15 (GrapheneOS, Pixel 8a, F-Droid)

Steps to reproduce

  1. Create a WebDAV share on a server such as Apache mod_dav.
  2. Store a file on the share with DAVx5 and read it once (for example by copying it with the Files app)
  3. Change the file on the server.
  4. Try to use to access the file on Android again; note that this fails because server returns HTTP status 412 because If-Match ETag on the GET that DAVx5 sends is no longer current.
  5. Try once more; note that it still fails with status 412 because DAVx5 still sends the old ETag (despite doing a PROPFIND on the directory and receving an updated ETag in the 412 response).
  6. Reboot (or wait for a while) and note that DAVx5 refreshes its cached ETag with HEAD. Reading the file now works.

Actual result

ETags seem to be cached from a prior HEAD request and not refreshed even when the WebDAV server returns status 412 from If-Match request.

Expected result

When the file changes on WebDAV server and the server returns 412 on GET, DAVx5 should refresh its ETag cache.

Further info

Since the server returns the current ETag with the 412 response to the GET, maybe pick that up? Alternatively since DAVx5 is doing a PROPFIND on the directory anyway, perhaps using the lp1:getetag property would be an option too?

If neither sounds good, re-doing HEAD on the target on 412 response seems like a surefire solution.

rfc2822 commented 1 day ago

I think we should drop headResponseCache completly: for every random-access file request, there should be a HEAD at the beginning that fetches the ETag and then for all operations this ETag is expected (otherwise an I/O error shall be returned).