Repository navigation
Conversation
Since 6.0.1 `save_files` writes thumbnails to `thumbs/<w>_<h>_<q>_<fit>_<location>/`, a path that no thumbnail URL points to, so the web server never serves them and every request is handled by PHP. Save them under the requested parameter string again, so the web server serves the next request for a thumbnail straight from disk. The parameter string and the filename come from the URL, so a thumbnail is not saved for: - a dot segment (`.`, `..`, `.htaccess`), or a path that changes when it is joined - a double-encoded filename, which Glide decodes again - a `?path=` query, which changes the image but not the URL path - parameters that are not understood, which would save a copy of the same thumbnail for every variant of the URL Those are still generated by PHP, as before.
A saved thumbnail is served by the web server with the same headers as any other image, e.g. in files/: Last-Modified and an ETag, but no lifetime. The request that generates it got Glide's one-year Cache-Control instead, which the firewall's use of the session turned into `private, max-age=0`. Serve the saved file from PHP as well, with the same headers, also when a request for an already saved thumbnail still reaches PHP, instead of generating and writing it again. The response stays private if the session was started, as it may set the session cookie.
The web server now serves saved thumbnails straight from disk, so deleting an image no longer took it off its thumbnail URLs: until 6.0.1 the thumbnails of a deleted image stayed public, and since 6.0.1 PHP replaced them with the error image only because no thumbnail was ever served from disk. Deleting a file or folder in the file manager now also removes its saved thumbnails. Deleting a file resolved its path relative to the working directory, which only worked because PHP runs from the web root. It is now resolved against the path of its location.
…exists Glide serves a generated image from its cache, also after the image itself was deleted. The next request for a thumbnail of a deleted image saved it again from that cache, so the web server served the deleted image once more. Only save a thumbnail if its image exists; otherwise the error image is served, as before.
PHP serves a thumbnail only until it is saved: from then on the web server serves the file, with its own ETag. Apache and Nginx each make it in their own format, so a browser that revalidated the response from PHP with its ETag got the whole thumbnail again instead of a 304. Send only Last-Modified, so the browser revalidates with If-Modified-Since, which any web server answers for the saved file.
Vondry
marked this pull request as ready for review
October 12, 2026 12:31
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since 6.0.1 (5161020)
save_fileswrites thumbnails tothumbs/<w>_<h>_<q>_<fit>_<location>/, a path no thumbnail URL points to. The web server never serves them, so every/thumbs/…request is handled by PHP.This supersedes #3828, which grew well beyond that fix. Its other changes will follow as separate PRs.
Changes
Save thumbnails under the requested parameter string again, so Apache / Nginx serve the next request from disk. Thumbnail URLs don't change, and neither do
public/.htaccessor the Nginx config. Nothing is saved for:.,..,.htaccess)foo/%252e%252e/kitten.jpgwould save a copy for every prefix)?path=query (it changes the image, not the URL path)…×crop×files×<anything>, which would fill the disk)These are still generated by PHP, as before.
Serve thumbnails with the same headers the web server sends for any image, e.g. in
files/. That'sLast-ModifiedandContent-Typeby extension, with no lifetime (Cache-Control: public), and 304 for conditional requests.ETag. Apache and Nginx build theirs from the file's size and mtime in their own format, so one sent by PHP never matches: a browser revalidating the copy it got from PHP got the whole file again.Last-Modifiedmatches, as both use the file's mtime.Cache-Control, which the firewall's use of the session turned intoprivate, max-age=0. Responses for a started session stay private, as they may set the session cookie.Deleting a file or folder in the file manager also removes its saved thumbnails. Since 6.0.1, PHP returned the error image for the thumbnail of a deleted image. A saved thumbnail served from disk would stay public instead.
Deleting a file resolved its path against the working directory, which only worked because PHP runs from
public/. It is now resolved against its location.Not changed
save_files: false, are served by Glide as before.Tests
ImageControllerTest(56 cases) covers:ThumbnailHelpergenerates?path=ThumbnailCacheClearerTestandFileDeleteThumbnailsTestcover removing the thumbnails of deleted files and folders, and that they aren't saved again afterwards.Each fix's tests fail without it.
I also checked four 6.1 sites under Apache 2.4 with PHP-FPM. The first request for a thumbnail is generated by PHP, and later ones are served from disk with the same headers as images in
files/. Revalidating either response gives a 304. Deleting an image in the file manager removes the file and its thumbnails, and its thumbnail URL then gets the error image.Upgrade: the
thumbs/<w>_<h>_…_files/folders saved since 6.0.1 are no longer used.bin/console cache:thumbsremoves them, along with thumbnails of images deleted outside the file manager (FTP, deploys). bolt/project needs no changes.Refs #3714. That PR saves under normalised parameters (
c→crop), so URLs using shorthand or the default fit still miss the saved file.