This module makes all image paths use protocol relative URLs with double “//“, which is normally great. However, this includes various social share meta tags that include image paths. If the protocol relative URLs from these tags are used to construct social share URLs, the image paths will not work, as the URL has nothing to determine the relative protocol from when it is embedded in a query string. Thus it seems that we need a way to selectively disable the rewriting of image paths for paths that will be used in metatag values.
I went exploring to attempt to find a solution and found that the only contextual information that the rewriting logic has available to it is the file URI. I ended up "solving" the issue by overriding the the cdn.file_url_generator
service class and put the following in my new generate()
method.
/**
* {@inheritdoc}
*/
public function generate($uri) {
if (strpos($this->getRelativeUrl($uri), '/social_share/') !== FALSE) {
return FALSE;
}
return parent::generate($uri);
}
This is obviously very brittle and not ideal, but it fixed the issue for us since all of our images used the same image style. I’m hoping that this issue can help provide a quick fix solution for others and also facilitate discussion of how we could fix this issue in a better way. Or perhaps this isn’t an issue for others due to the way they are handling social share images and if I took an alternate approach I could avoid this issue entirely.
Another potential approach is adding a rewriting disabled property to the FileUrlGenerator
class that other modules can toggle on and off. Then the metatag module (or any other module) could disable rewriting while it renders its token values, and then re-enable the rewriting upon conclusion. I haven't tested this approach yet, as I wanted to get some general feedback before I started working on a more robust solution.
It should be noted that the Metatag module strips double “//“ from token values and replaced it with a single/
, so even if the issue noted here doesn’t cause an issue with your metatag image paths, they will still be broken. I filed this issue to begin discussion in the metatag issue queue for this semi-related issue.
Comments
Comment #2
Wim LeersMarking that other issue you filed as a related one.
Comment #3
Wim LeersYep, the need for the context in which the file URL will appear is once again haunting us :( This was a problem in Drupal 7, and still is in Drupal 8, because the "file URL" API is identical.
Can you point me to where exactly the image URL is being generated though? There's zero calls to
file_create_url()
in themetatag
module. It pretty much must be theurl
token that thefile
module provides. That does this:The comment there describes a related problem, which in fact points to exactly the same problem that we're encountering here, with the exact same root cause: the lack of context-awareness. This time in the Token system, where it's arguably an even bigger/more fundamental flaw.
Conclusion: this problem is caused by design flaws in both the file URL system and the token system. Both need to be context-aware, but aren't. This is going to be tough to solve.
Comment #4
Wim LeersThe comment I quoted was added in #1494670-77: References to CSS, JS, and similar files should be root-relative URLs: avoids mixed content warnings & fewer bytes to send.
Comment #5
Wim LeersSo I agree that the CDN module's file URL altering should be context-aware, but it can't be, because the file URL system is not context-aware. We're limited by the abstraction we use.
However, thinking a bit more about this exact use case…
I don't think this makes sense. I don't see a reason why it would not be okay to use protocol-relative URLs in meta tags. All protocol-relative URLs in a HTML document must be evaluated with the document's protocol inserted instead. All relative URLs in a HTML document must be evaluated with the document's
<base>
element's base URL inserted instead. And so on.<meta>
tags live in a HTML document. Hence URLs in<meta>
tags must also be evaluated according to these rules.So:
<meta>
tags are fine, themetatag
module should not break them: #2840751: Protocol-relative URLs are broken must be fixedComment #6
Wim LeersSo, to the best of my knowledge, the CDN module is working as correctly as it can, the Metatag has a bug to be fixed. (And turns out the D7 version of the Metatag module had the exact same bug fixed a few months ago: #2791963: Protocol Relative URLs not handled properly.)
Comment #7
adamzimmermann CreditAttribution: adamzimmermann at Chromatic commentedThank you for digging into all of this so thoroughly and quickly.
I think this is what you are asking for
Drupal\metatag\MetatagToken::replace()
. Then this is the line that generates the URL.$replaced = $this->token->replace($string, $data, $options);
So essentially, what you said about it being the URL token is correct. I was using an image field value token when I discovered this.
I assume you ruled out my idea with a property that we could toggle that would allow other modules to temporarily enable/disable CDN rewriting? I'm curious why that wouldn't potentially work.
They are fine in the context of the page, but we ran into this issue since we use these values to populate image URLs that we put in social share query strings, such as Pinterest or Facebook. The shared "media" URL wouldn't work in the popup that our Pinterest button created.
https://www.pinterest.com/pin/create/button/?url=http://example.com&media=//example.cdndomain.com/cdn/farfuture/mZRxNljyhBA6tIH8ozCr-uQC1ybvCaBRrUW94h7O0gg/1482159252/sites/example.com/files/styles/social_share/public/product/image.png&description=Example description" data-pin-shape="round"></a>
Again, perhaps others aren't taking this approach, and that is why this hasn't been previously reported.
Comment #8
Wim LeersThis would make the CDN module be dependent on global state. Which can cause all sorts of problems. It's a
canoil tanker of worms that I'd rather not open.Then the logic over there needs to be updated; it should be able to handle non-absolute URLs, and convert them to absolute URLs when necessary.
Finally, I want to stress #2840751-5: Protocol-relative URLs are broken again — you can see that the same bug existed in the D7 version of Metatag!
Comment #9
adamzimmermann CreditAttribution: adamzimmermann at Chromatic commentedOpening a can of worms is never good. Ya, it definitely seems to makes sense to leave it as given all of that.