How to use GitHub
- Please use the 👍 reaction to show that you are interested into the same feature.
- Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
- Subscribe to receive notifications on status change and new comments.
Is your feature request related to a problem? Please describe.
When sharing a file or folder via a public link, Nextcloud serves the download in a way that does not enable functioning caching. It sets cache-control: must-revalidate, post-check=0, pre-check=0, which asks browsers to revalidate each request (which could be okay), but it does not set last-modified or etag, and it does not respect if-modified-since or if-none-match requests.
For an image file preview of a public share, caching works: cache-control includes a max-age, the last-modified response header gives the date the preview was first requested (I assume), and conditional requests with a recent enough if-modified-since return status 304.
(On a side note, "pragma: no-cache" in the response is deprecated, and "post-check" and "pre-check" were never standardized in the "cache-control" header.)
Describe the solution you'd like
The PublicPreviewController uses a FileDisplayResponse to serve the file preview with proper cache control.
Something similar would be nice for the ShareController. That is, instead of forbidding caching in sendHeaders, set the last-modified header to the file modification date and possibly set an etag, and return a 304 response in getSingleFile when appropriate.
Describe alternatives you've considered
My use case is to embed shared files in web pages. The alternative would be to set up a web server to serve static files. Using Nextcloud to do so is not very efficient, but can be handy. For this, it would be useful to avoid needless re-requests of downloads by clients.
Additional context
Simulation of getting a preview URL for the first time:
$ curl -I 'https://SERVER/index.php/apps/files_sharing/publicpreview/SHAREID?file=/&fileId=FILEID&x=1920&y=1200&a=true&etag=ETAG'
HTTP/2 200
date: Fri, 17 May 2024 17:38:01 GMT
pragma: no-cache
x-request-id: ZkeV-S6ejSRIelV3YpDT0wAAAQc
cache-control: private, max-age=86400, must-revalidate
content-security-policy: default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
feature-policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'
x-robots-tag: noindex, nofollow
content-disposition: inline; filename="512-512-max.jpg"
expires: Sat, 18 May 2024 17:38:01 +0000
set-cookie: SOME COOKIES
referrer-policy: no-referrer
x-permitted-cross-domain-policies: none
x-xss-protection: 1; mode=block
last-modified: Fri, 17 May 2024 14:20:28 GMT
etag: "98ce490be53325b5f254d210cbab4624"
content-length: 60210
content-type: image/jpeg
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
strict-transport-security: max-age=31536000
Simulation of getting a preview URL for the second time:
$ curl -I 'https://SERVER/index.php/apps/files_sharing/publicpreview/SHAREID?file=/&fileId=FILEID&x=1920&y=1200&a=true&etag=ETAG' -H 'If-Modified-Since: Fri, 17 May 2024 17:38:01 GMT'
HTTP/2 304
(followed by all the same headers as before)
Getting a download URL:
$ curl -I 'https:/SERVER/index.php/s/SHAREID/download/test.jpg'
HTTP/2 200
date: Fri, 17 May 2024 17:41:41 GMT
content-security-policy: default-src 'self'; script-src 'self' 'nonce-NONCE'; style-src 'self' 'unsafe-inline'; frame-src *; img-src * data: blob:; font-src 'self' data:; media-src *; connect-src *; object-src 'none'; base-uri 'self';
pragma: no-cache
content-disposition: attachment; filename*=UTF-8''test.jpg; filename="test.jpg"
content-transfer-encoding: binary
expires: 0
cache-control: must-revalidate, post-check=0, pre-check=0
x-accel-buffering: no
set-cookie: SOME COOKIES
referrer-policy: no-referrer
x-permitted-cross-domain-policies: none
x-robots-tag: noindex, nofollow
x-xss-protection: 1; mode=block
content-length: 63834
content-type: image/jpeg
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
strict-transport-security: max-age=31536000
Adding an if-modified-since to the last request does not change the outcome.
How to use GitHub
Is your feature request related to a problem? Please describe.
When sharing a file or folder via a public link, Nextcloud serves the download in a way that does not enable functioning caching. It sets
cache-control: must-revalidate, post-check=0, pre-check=0, which asks browsers to revalidate each request (which could be okay), but it does not setlast-modifiedoretag, and it does not respectif-modified-sinceorif-none-matchrequests.For an image file preview of a public share, caching works:
cache-controlincludes amax-age, thelast-modifiedresponse header gives the date the preview was first requested (I assume), and conditional requests with a recent enoughif-modified-sincereturn status 304.(On a side note, "pragma: no-cache" in the response is deprecated, and "post-check" and "pre-check" were never standardized in the "cache-control" header.)
Describe the solution you'd like
The
PublicPreviewControlleruses aFileDisplayResponseto serve the file preview with proper cache control.Something similar would be nice for the ShareController. That is, instead of forbidding caching in sendHeaders, set the
last-modifiedheader to the file modification date and possibly set anetag, and return a 304 response ingetSingleFilewhen appropriate.Describe alternatives you've considered
My use case is to embed shared files in web pages. The alternative would be to set up a web server to serve static files. Using Nextcloud to do so is not very efficient, but can be handy. For this, it would be useful to avoid needless re-requests of downloads by clients.
Additional context
Simulation of getting a preview URL for the first time:
Simulation of getting a preview URL for the second time:
(followed by all the same headers as before)
Getting a download URL:
Adding an
if-modified-sinceto the last request does not change the outcome.