I have this function in my functions.php file:
function dns_prefetch_to_preconnect( $urls, $relation_type ) {
if ( 'dns-prefetch' === $relation_type ) {
$urls = [];
}
if ( 'preconnect' === $relation_type ) {
$urls = wp_dependencies_unique_hosts();
}
return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );
It takes the URLs defined in wp_dependencies_unique_hosts()
– which WordPress by default assigns to the dns-prefetch
link tag – and reassigns them to the preconnect
link tag. The function was provided to me here:
Change dns-prefetch to preconnect for external enqueued resources
However, this function isn't working entirely correctly. It adds the preconnect
URLs using http instead of https.
Example: when I'm not using the above function, WordPress adds this link to my header:
<link rel='dns-prefetch' href='//fonts.googleapis' />
And when I enable the above function, it replaces that link with this link:
<link rel='preconnect' href='' />
The problem, of course, is that it should be https, not http.
Can someone help me modify my function so that it gives me https links?
I have this function in my functions.php file:
function dns_prefetch_to_preconnect( $urls, $relation_type ) {
if ( 'dns-prefetch' === $relation_type ) {
$urls = [];
}
if ( 'preconnect' === $relation_type ) {
$urls = wp_dependencies_unique_hosts();
}
return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );
It takes the URLs defined in wp_dependencies_unique_hosts()
– which WordPress by default assigns to the dns-prefetch
link tag – and reassigns them to the preconnect
link tag. The function was provided to me here:
Change dns-prefetch to preconnect for external enqueued resources
However, this function isn't working entirely correctly. It adds the preconnect
URLs using http instead of https.
Example: when I'm not using the above function, WordPress adds this link to my header:
<link rel='dns-prefetch' href='//fonts.googleapis' />
And when I enable the above function, it replaces that link with this link:
<link rel='preconnect' href='http://fonts.googleapis' />
The problem, of course, is that it should be https, not http.
Can someone help me modify my function so that it gives me https links?
Share Improve this question edited Jan 4, 2020 at 17:40 GermanKiwi asked Jan 4, 2020 at 0:08 GermanKiwiGermanKiwi 5511 bronze badges 4 |2 Answers
Reset to default 1The problem is not that the function you're using adds http:
, the problem is it adds no URL schema at all!
As a result, WP needs to add a URL schema to turn the host into a URL, and so it uses http://
. It has no way of knowing what the original was, or if the host supports HTTPS, so http://
is the safe bet.
If however you passed the array with URL schema added, it would be passed through without issue.
Something like this may do the trick:
$hosts = wp_dependencies_unique_hosts();
$urls = array_map( function( $host ) {
return set_url_scheme( $host, 'https' );
}, $hosts );
In the longrun though, it would be better to get the actual URLs and distill the host URL out of them, rather than relying on wp_dependencies_unique_hosts
if you wanted to preserve the mixture of http
and https
I've finally got it working now, as follows:
First I found the original wp_dependencies_unique_hosts()
function from the WordPress code (it's in a file called general-template.php), and I made a copy of it, but giving it a new name: wp_dependencies_unique_urls()
.
I observed that this function is using wp_parse_url()
to grab just the host part of each URL from the list of scripts and styles. In other words, it's dropping the scheme, which is the reason for the problem I'm having.
So I modified the function to include the scheme - here it is in its entirety:
function wp_dependencies_unique_urls() {
global $wp_scripts, $wp_styles;
$unique_urls = array();
foreach ( array( $wp_scripts, $wp_styles ) as $dependencies ) {
if ( $dependencies instanceof WP_Dependencies && ! empty( $dependencies->queue ) ) {
foreach ( $dependencies->queue as $handle ) {
if ( ! isset( $dependencies->registered[ $handle ] ) ) {
continue;
}
$dependency = $dependencies->registered[ $handle ];
$parsed = wp_parse_url( $dependency->src );
if ( ! empty( $parsed['host'] ) && ! in_array( $parsed['host'], $unique_urls ) && $parsed['host'] !== $_SERVER['SERVER_NAME'] ) {
$unique_urls[] = $parsed['scheme'] . '://' . $parsed['host'];
}
}
}
}
return $unique_urls;
}
As you can see, the main thing I've changed is this:
$unique_urls[] = $parsed['scheme'] . '://' . $parsed['host'];
I hope this is the best way to add the scheme to the beginning of each URL.
Next, I modified my original function (from my original question above) so it calls this new function I've created:
function dns_prefetch_to_preconnect( $urls, $relation_type ) {
if ( 'dns-prefetch' === $relation_type ) {
$urls = [];
}
if ( 'preconnect' === $relation_type ) {
$urls = wp_dependencies_unique_urls();
}
return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );
Et voila, it works! I now have valid 'preconnect' links in my page headers, which use the same scheme as the original enqueued scripts and styles - either http or https!
And if I want to, I can combine my two functions into one big function for simplicity:
function dns_prefetch_to_preconnect( $urls, $relation_type ) {
global $wp_scripts, $wp_styles;
$unique_urls = array();
foreach ( array( $wp_scripts, $wp_styles ) as $dependencies ) {
if ( $dependencies instanceof WP_Dependencies && ! empty( $dependencies->queue ) ) {
foreach ( $dependencies->queue as $handle ) {
if ( ! isset( $dependencies->registered[ $handle ] ) ) {
continue;
}
$dependency = $dependencies->registered[ $handle ];
$parsed = wp_parse_url( $dependency->src );
if ( ! empty( $parsed['host'] ) && ! in_array( $parsed['host'], $unique_urls ) && $parsed['host'] !== $_SERVER['SERVER_NAME'] ) {
$unique_urls[] = $parsed['scheme'] . '://' . $parsed['host'];
}
}
}
}
if ( 'dns-prefetch' === $relation_type ) {
$urls = [];
}
if ( 'preconnect' === $relation_type ) {
$urls = $unique_urls;
}
return $urls;
}
add_filter( 'wp_resource_hints', 'dns_prefetch_to_preconnect', 0, 2 );
wp_dependencies_unique_hosts
are just hosts, they aren't URLs and don't have a schema. Have you confirmed it is indeedhttp://
and that this isn't something the browser is adding? There should be no schema at all based on the code in your question – Tom J Nowell ♦ Commented Jan 4, 2020 at 1:55wp_dependencies_unique_hosts
returned no hosts – Tom J Nowell ♦ Commented Jan 4, 2020 at 2:43'tomjn'
it will prefix it withhttp://
as it doesn't know what the correct schema is, and it can't usehttps://
as the host may not support it.'https://tomjn'
however works as expected – Tom J Nowell ♦ Commented Jan 4, 2020 at 2:46wp_dependencies_unique_hosts
is, indeed, just a list of hosts without any scheme. I agree with your conclusion that WordPress is adding 'http' as the scheme when the scheme isn't already there. – GermanKiwi Commented Jan 6, 2020 at 23:03