The function image_style_url() is setting a cache entry which will later be checked by image_style_generate() to grant access. However, if the file already exists then the cache entry is not set which results in an access denied message if this happens on a page that got the cache cleared.
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | image_style_url_d7_827206.patch | 1.13 KB | jurgenhaas |
Comments
Comment #1
jurgenhaasApplied patch should resolve this.
Comment #2
dawehnerThis looks fine for me. But we might should be able to test this.
This code stops to run and never set the cache when $destination does exists.
Comment #3
andypostI think current implementation is right because logic a bit different.
image_style_url() sets cache and URL to 'image/generate/' (causing to call image_style_generate()) and disables page cache only for first time when derivated image will be generated.
So cache entry exists a small amount of time when URL points to image_style_generate() ONLY when derivated image should be regenerated or created.
But when image already exists the image_style_generate() should never be executed!
Comment #4
jurgenhaasWell, I'm not quite sure I could agree with this, unless there are different functions for something similar elsewhere.
Calling image_style_url() returns a URL to an image which can be included as [img src="image/generate/.../.../name.jpg"] in the data somewhere and this will display the right image regardless whether this exists already or not. You can be sure it will be generated if it didn't exist at the time you needed it.
But that's where the problem begins: you have that URL "inage/generate/..." in your html data and that calls image_style_generate() which returns an access_denied() even if the required image does exist.
This scenario doesn't make sense to me and I wonder if I'm using this in a wrong way and hope to get some suggestions from you guys on how to do this in a better way.
Comment #5
andypost@jurgenhaas could you explain a case when image_style_generate() will return access_denied() ? Could you write a test for this case?
As I said above: 'image/generate/...' used ONLY when no image exists and this html is not cached!
So image_style_url() used to return URL and this links could be DIRECT and 'image/generate/...' IN second case this sets cache causing image_style_generate() to generate image so all other calls to image_style_url() will return DIRECT links to file
Comment #6
jurgenhaasThe test case is simply a node which contains
You can see an example here: http://www.sorina-nwachukwu.de where all images are coded that way.
This is *always* throwing an access denied because of the line
in image_style_generate(). This is why I call image_style_url() for each image before delivering the page, but that only works if the cache_set() is called earlier as described above.
Comment #7
catchI think the issue here is you should not be embedding those links in HTML. It looks like re-using the code from theme_image_style() would both ensure the preset is generated if it doesn't exist, and also give you a url which will always work.
http://api.drupal.org/api/function/theme_image_style/7
Downgrading this since I'm sure this works fine otherwise, but we should document that the function should never be used directly to generate HTML output.
Comment #8
jurgenhaasOK, that's what I thought. It was quite handy to use that function but I expected that to be the wrong way.
Comment #9
catchI looked at this a bit closer, and I'm putting it back to critical.
image_style_url() prevents stale links from being created via drupal_page_is_cacheable(FALSE), however that's not the only situation where HTML might be cached:
* block caching
* render caching
* panels / views caching
* something like http://drupal.org/project/inline or http://drupal.org/project/filefield_insert where the filter output might be generated with an image/generate path but then cached in the filter module or by text module.
In all of those cases, it'd be possible to cache an image/generate path in the HTML - in fact it's quite likely that you have cache miss for HTML at the same time as a miss for the image style.
I can't think of many ways around this except for adding something like drupal_html_is_cacheable(), which all HTML caching methods could then check before trying to cache_set(), and image.module could use when generating images.
Comment #10
moshe weitzman commentedI don't understand image_style_url(). Why do we have different URLs for the case when we need to generate versus the case when we don't. Isn't the whole point to generate an image iff we got a miss? If we can unify on a single URL, then it won't matter if it gets cached.
Comment #11
eojthebraveI believe the reason for having two URLs is so that once a derivative image has been generated we can just link to it directly and let Apache deal with serving the image rather than getting Drupal involved for every image request on the page every single time.
Comment #12
Anonymous (not verified) commentedi'm with moshe in not understanding this.
imagecache in D6 relied on our mod_rewrite rules in .htaccess, which will only pass the request to Drupal if the file doesn't exist.
so, the url for a style would always be the same. if it the path points to a file that doesn't exist, imagecache generates the image and serves it, but all other requests are just served directly. if that's not the case now in core, something is very wrong.
Comment #13
tstoecklerSo instead of what we have now at http://api.drupal.org/api/function/image_style_url/7 we would be doing something like (hypothetical):
???
Comment #14
tstoecklerActually that might not be so good in case you are viewing many images (gallery) and have just flushed a preset, as you would be recreating every single derivative on one page view. Hmm...
Comment #15
Anonymous (not verified) commentedok, i had a look at the code here, and, well, it just looks wrong now we have a locking framework. Damien informed me that image.module went in before we had a locking framework, but now we have one, i think we should move to something like the way imagecache does it.
that is, image.module should claim any paths its needs to via image_menu(), so that there's no difference between the url that generates a derivative and serves it from disk.
i'll try to ping dries and webchick to see if there's any chance we can fix this for D7.
Comment #16
moshe weitzman commentedMW: Skip this comment. It's just wrong and confusing
I don't think we can keep the current approach for D7. We have lost one of the main advantages of imagecache and thats that derivitave building can no lo lober be off-loaded to a separate web server like media.example.com. With the current code, we force all webservers to generate derivitaves. Once again, the fix is to generate derivitaves during the image request not the original HTML request.Comment #17
catchAs far as I can see we're still creating derivatives during the image request - the issue is that the url generated for the
tag differs depending on whether the file is found or not.
Comment #18
moshe weitzman commentedoops. ignore my dumb-ass comment there. thanks catch.
this is still a mess tho.
Comment #19
Anonymous (not verified) commentedspoke to quicksketch about this in #drupal. we generate at one url, and serve the image at another because we can't make image.module depend on mod_rewrite.
that's a huge bummer, but we're stuck with it.
so, we're back to solving the side effects caused by this.
Comment #20
Anonymous (not verified) commentedpostponing this issue in favour of #851878: serve image derivatives from the same url they are generated from. we may just be able to kill this issue once the other one goes in.
Comment #21
damien tournoud commentedAll of this is taken care of in #827206: image_style_url() only prevents page caching.
Comment #22
mstrelan commentedThis is closed a duplicate of itself?