Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Link field only accepts external URLs with "http://" or "https://". It should also support protocol-relative URLs e.g "//example.com". Otherwise we're limiting URLs for no good reason, which is simply a Drupalism.
Proposed resolution
Allow
Remaining tasks
Discuss the need of the double slash at the beginning of protocol relative URLs, accepting "example.com" as a valid external URL.
User interface changes
None.
API changes
API addition: Url::fromUri()
supports protocol-relative URLs.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#62 | url_protocol_relative-2573635-62.patch | 2.51 KB | Wim Leers |
Comments
Comment #2
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedThe protocol is needed to differentiate between internal and external links.
If there is no protocol specified Drupal will check if it is a valid internal link.
The proposed solution,
"//example.com"
, would use//
just for omittinghttp:
orhttps:
. This is not a common URL elsewhere and would be considered a "drupalism".Comment #3
tannerjfco CreditAttribution: tannerjfco commentedThere is nothing about a protocol-agnostic URL that is a "drupalism". However, I will grant in thinking more through it, I'm uncertain there's a use-case for it as a user entering content. The most common case of entering a link would likely be copy/pasted from somewhere, so the link would get whatever protocol is valid when copied. I think its worth having this open for further consideration for or against beyond the "drupalism" concern, I believe it is technically a valid scheme.
Comment #4
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedChanged "//example.com" to "example.com" at the issue summary. Then, it will not sound as a drupalism.
Leaving it open for discussion, as there still the technical problem differentiating between internal and external links.
Comment #5
tannerjfco CreditAttribution: tannerjfco commentedagain, nothing about this is a drupalism. //domain.com is technically a valid scheme
Comment #6
rootworkJust for some background -- protocol-relative (or protocol-agnostic) URLs were popularized by Paul Irish back in 2010. They're particularly useful for frontend assets from third-parties. For instance, if you're loading a web font from Typekit, and you use
http://
on a site that exists onhttps://
, you'll get a mixed-content security warning. By using the protocol-relative URL, the browser will load whichever is appropriate to how the site is being served. Though it's worth pointing out that Paul Irish now considers this an anti-pattern, because https should now always be used.I'm not sure there's a concrete use case for this in the link module, but that's how these URLs get used in the context of theming.
Comment #7
attiks CreditAttribution: attiks at Attiks commentedThe HTML5 url field allows protocol-less URI, if a user enters //google.com the link isn't even rendered, but it is shown in edit mode correctly
This sounds like a major bug, because it will confuse people
Comment #8
dawehnerHere is a patch for it.
Comment #9
attiks CreditAttribution: attiks at Attiks commentedSwitching version so it gets tested
Comment #10
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedI think the correct term is protocol-relative.
Comment #11
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedper #6needs justification in the issue summary as to why you shouldn't use https:// if the content you are linking to can be served that way. We could just throw a more specific exception?
Comment #12
rootworkSo here's what Paul Irish writes in his update, calling protocol-relative URLs an anti-pattern, that I referenced in #6:
I think it's significant that he says asset. That's the context in which this technique was originally developed (as I mentioned above) and where it usually shows up: Calling things like CSS, JS and font files from third-party services. And given that most good third-party services now run on HTTPS, it makes sense to only request those assets on HTTPS, even if you're on HTTP.
But link module fills a different need, which is linking to all kinds of things, as outbound links, not necessarily for front-end/asset-requesting reasons. Given that, I don't think protocol-relative URLs are necessarily an anti-pattern, because you might be linking out to sites whose protocol you don't know.
(Admittedly I can't think of an example scenario like that, but I'm not sure what the scenario was for the OP either.)
So my reading is that given the use case of link module, protocol-relative links might be legitimate, and not the anti-pattern that Paul Irish describes for asset requests. But perhaps we want a concrete example to confirm that.
Comment #13
attiks CreditAttribution: attiks at Attiks commentedComment #14
dawehnerIn general I kinda think we should implement what is possible, and well protocol relative URLs are a thing on the internet.
Comment #15
cilefen CreditAttribution: cilefen commented@dawehner But only for included assets, not links.
Comment #16
attiks CreditAttribution: attiks at Attiks commentedIt isn't asset specific, it can be used for links as well.
Comment #17
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedIn what case does it make sense to have a protocol-relative link?
For assets like external JS or images, the idea was to load the JS or image over https if the current page was https to avoid mixed content warnings.
When would it be important or even appropriate to toggle an external link between http and https based on the protocol the current page is using?
Comment #18
cilefen CreditAttribution: cilefen commented@pwolanin I agree, this issue makes no sense to me.
Comment #19
dawehnerWell, I believe strongly that the URL object, as being an abstract concept, should support what browsers support. Whether this is also needed for the link field, I'm not sure.
Comment #20
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedI like the patch at #8 because without the patch Drupal does not display any error message yet, the published node does not display the link if typing
//example.com
. After patched the link is displayed as//example.com
.I am marking it as "needs work" because the error message displayed if typing
example.com
is this: "Manually entered paths should start with /, ? or #. "This error message is regarding internal links only. We should change it to something like: "Manually entered internal paths should start with /, ? or #. External paths should start with //, or a protocol such as https://"
@dawehner I agree with your last comment at #19. When I said it looks like a drupalism I mean I never seen a browser which I had to type // at the address. IMHO, it sounds much better for user experience if we could find a way to just accept
example.com
as an external link without the double slash. Do you guys it worth more discussion about keeping/removing the double slash? - I'm adding it to the issue summary.Comment #21
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedI changed the error message to display as said in comment #20
I also added code to trim the external URLs starting with
//
because it may be weird to end users and site visitors to see a link in content such as//example.com
with no leading protocol.Comment #23
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedFixed the failing test at #21
Comment #24
dawehnerIMHO the field widget itself have some description which points out that you can use
https://...
The other case: using "//" is IMHO fine to not be described somehow to the user.
Comment #25
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commented@dawehner as an end user I would expect
example.com
to be a valid input. The current field widgets description nor its error message do not explain clearly why this is not a valid input. Then, this different error message is relevant in this case.I would prefer to change the whole field validation to accept
example.com
, but this is a task for another issue and I am not sure this would be possible to be done with the validations we have for internal links. Anyway, something to be discussed in a different issue.BTW, I agree on not adding the
//
use case in the field widget description, as it could be more confusing than helpful.Comment #27
slatty CreditAttribution: slatty commentedHere is a patch for 7.x-1.x
Comment #29
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedComment #30
kostyashupenkowell, i could apply the last patch from #23 using 8.1.x branch, so no need to reroll it
Comment #31
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedit seems the failed test belongs to a deleted comment
Comment #32
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commentedComment #33
Wim LeersMarked #2710785: \Drupal\Core\Url::fromUri('//example.com') - allow wildcard HTTP scheme as a duplicate.
Comment #36
dimaro CreditAttribution: dimaro at La Drupalera by Emergya commentedPatch against 8.1.x
Simple rebase fixed it.
Comment #37
rootworkConfirmed that the patch applies and does what it says.
Screenshots of the "front-end" are the same, as it should be.
Edit page, with or without patch:
Node, with or without patch:
What changes is the linked URL. Without the patch, the linked URL is simply empty:
With the patch, the URL is correctly linked:
Comment #38
Wim LeersNit: s/protocol relative/protocol-relative/
Can be fixed on commit.
Comment #39
lluvigneHi all,
I try to fix the nits before apply. Hope that i understood you correctly.
Comment #40
Wim LeersComment #41
dawehnerIts nice to see this done properly. In earlier comments both @pwolanin and @cilefen disagreed with the feature itself. I'm wondering whether their concerns got addressed.
For me, this feature simply belongs into the system, given that we support all kind of URLs already. Additionally protocol relative URLs are super useful for assets.
Comment #42
alexpottI don't think @pwolanin and @cilefen concern's have been addressed at all. And given we ask users to prefix with a leading slash all over the place. I haven't seen a convincing argument that the UI should support protocol relative link fields. I think there is an argument that the URL API should.
Comment #43
dawehner@alexpott
On thing we could do is to support it but don't hint the capability to users.
Comment #44
rootworkI agree the URL API should support this, but if it is going to confuse people I don't think we necessarily need to explain it, as @dawehner suggests.
Since protocol-relative URLs are valid, I think Drupal should support them.
However, it is mostly something used in assets (see background links in #6 and #12), which are usually not set through the UI but through theme or module files, so I've been trying to think of a use case to address @pwolanin and @cilefen's concerns.
So here's one: Imagine a contrib module that takes a value from a link field on a node and inserts it on the page. It could be third-party JS (say an analytics add-on script for a landing page), an external image (say set as a the background on the entity), or CSS hosted on a CDN (say inlining critical styles).
Admittedly that seems like a clumsy way of doing things -- relying on a core link field instead of the module creating its own -- but it's possible.
Still, the strongest argument to me is that they are valid URLs, and Drupal should accept valid URLs as valid. Use case or no use case, we shouldn't have some weird Drupalism exception to a valid URL.
Comment #45
Wim Leers#44++, and especially:
If this gets knocked down again from RTBC, then I propose we do #2710785: \Drupal\Core\Url::fromUri('//example.com') - allow wildcard HTTP scheme, which is just the URL API portion of this. Then that portion can at least land.
Comment #46
Wim LeersComment #47
dawehnerIMHO ideally we should still keep the UI text as it is ... I could imagine that people could be confused by that sentence.
Comment #50
alexpottDiscussed with @catch. We think the API changes should land and we’ll hold off on the link field until there’s a use-case beyond “it’s a valid URL” since the use-case of attaching assets via a link field is something we should discourage.
I think just making the API changes in this issue is okay since it'll make crediting the contributors easier.
Comment #51
alexpottFor #50
Comment #52
Wim LeersOkay, I'll reroll this patch, rescope this issue, and file a new issue for the Link field aspects.
Comment #53
Wim LeersAs of #50, the scope of this issue is solely about making
Url::fromUri()
work with protocol-relative URLs. That means the scope of this issue is now effectively identical to #2710785: \Drupal\Core\Url::fromUri('//example.com') - allow wildcard HTTP scheme, but for practical reasons (see #50), we chose to do it in this issue instead.I opened the follow-up #2744729: Link field should accept protocol-relative URLs to do what this issue originally intended to do.
And finally, attached is a rerolled patch that only keeps the hunks that are relevant for
Url::fromUri()
.Comment #54
Wim LeersAnd to be perfectly clear: this does belong in Drupal 8.1, not in Drupal 8.2, because it's an oversight, a bug, that prevents certain contrib modules from working.
I personally maintain the CDN module, which transforms file URLs into protocol-relative URLs pointing to a CDN. Without this API support, it simply cannot function, because PHP errors will be thrown in many places, including when uploading files (when a file is uploaded, a preview to that file is rendered). See #2711529: File upload widget broken when using CDN module, fixed in Drupal 8.1.4: require that version.
Comment #55
dawehnerI would have went the other way round and added a new issue for the URL change, given how much discussion already existed around link field, but meh.
Comment #56
Wim LeersI agree, but
In the end, it won't matter all that much :)
Comment #57
neclimdulnit: the documentation should be above the ifelse that handles protocol relative URLs, not the section that handles internal protocols.
As Wim mentioned in IRC, that can be fixed on commit. The rest looks very well defined and solid.
Comment #58
alexpottThis change seems out of scope... since later on in this method we do:
Which this will have stopped from happening afaics.
Comment #59
Mac_Weber CreditAttribution: Mac_Weber as a volunteer commented@alexpott @catch let's think the opposite way. Is there a reason for NOT supporting a valid URL?
I do not agree with the arguments on #50.
Just as @Wim Leers said on #45 I also think the argument on #44 is very strong:
Comment #60
Wim Leers#57: Fixed.
#58: AFAICT you're right. It seems to have been a work-around for a UI problem, and likely an incorrect work-around. Thanks for your strictness. Apologies for my lack of strictness.
#59: the thing is that there is an usability impact. So, let's first land the API support here.
Comment #61
BR0kEN@wim-leers, superb. You've developed a patch that I've already did: https://www.drupal.org/node/2710785#comment-11110037
Comment #62
Wim Leers#61: no need for the sarcasm. We have one common goal here. See #48 — you're credited. So don't worry ;) I don't care about the issue credit. I only care about getting this fixed.
In fact, I see you've got an extra test there that is very valuable! :) So, bringing that into this patch. And I see that one part was not yet tested: whether protocol-relative URLs are correctly considered as external by the
Url
class.Comment #63
neclimdulGreat minds think alike I guess. :) Too bad it didn't get more attention earlier but we got there eventually.
It might be nice to rewrite the main testcase test to confirm all the outputs like the new test does but that is definitely overkill here. Especially because it might be that is actually impossible. If someone wanted to do that in a follow up I'd definitely review it though. :)
Thanks again guys!
Comment #64
alexpottCommitted a8d3c98 and pushed to 8.1.x and 8.2.x. Thanks!
Comment #67
Wim LeersThanks! This is one important blocker less for the CDN module to get a stable Drupal 8 release!
See #2711529-10: File upload widget broken when using CDN module, fixed in Drupal 8.1.4: require that version.
(Sadly, #2313917-67: Core version key in module's .info.yml doesn't respect core semantic versioning and #2641658-22: Module version dependency in .info.yml is ineffective for patch releases mean that modules can't actually declare a patch version of Drupal 8 as the minimum version…)
Comment #69
liquidcms CreditAttribution: liquidcms commentedBeen through a couple of these issues now and wondering if someone can point me to the one that covers the basic issue which i think started these:
I tried this patch and the one here #2744729: Link field should accept protocol-relative URLs and unclear that either of these does anything.