Skip to content

Commit

Permalink
Closes #3423 Add preconnect tag for CDN URLs (#3463)
Browse files Browse the repository at this point in the history
* Add add_preconnect_cdn() method

* Add integration test draft and notes.

* Implement preconnect for non-crossorigin cdn-urls

* Add fixture, adjust integration test

* Revise forcorrect cdn urls, use crossorigin second

* Run phpcbf

* Update CDN preconnect testcases

* Use agnostic scheme when not provided

* Rerun phpcs

* Clean dns-prefetch out of testcases :)

* Add testcase/solution for `test/tests`
  • Loading branch information
iCaspar committed Mar 23, 2021
1 parent fc422b7 commit bcc54d0
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 4 deletions.
76 changes: 73 additions & 3 deletions inc/Engine/CDN/Subscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Subscriber implements Subscriber_Interface {
* Constructor
*
* @param Options_Data $options WP Rocket Options instance.
* @param CDN $cdn CDN instance.
* @param CDN $cdn CDN instance.
*/
public function __construct( Options_Data $options, CDN $cdn ) {
$this->options = $options;
Expand All @@ -55,6 +55,7 @@ public static function get_subscribed_events() {
'rocket_css_url' => [ 'add_cdn_url', 10, 2 ],
'rocket_js_url' => [ 'add_cdn_url', 10, 2 ],
'rocket_asset_url' => [ 'maybe_replace_url', 10, 2 ],
'wp_resource_hints' => [ 'add_preconnect_cdn', 10, 2 ],
];
}

Expand All @@ -64,6 +65,7 @@ public static function get_subscribed_events() {
* @since 3.4
*
* @param string $html HTML content.
*
* @return string
*/
public function rewrite( $html ) {
Expand All @@ -80,6 +82,7 @@ public function rewrite( $html ) {
* @since 3.4.0.4
*
* @param string $html HTML content.
*
* @return string
*/
public function rewrite_srcset( $html ) {
Expand All @@ -96,6 +99,7 @@ public function rewrite_srcset( $html ) {
* @since 3.4
*
* @param string $content CSS content.
*
* @return string
*/
public function rewrite_css_properties( $content ) {
Expand Down Expand Up @@ -155,6 +159,7 @@ public function get_cdn_hosts( array $hosts = [], array $zones = [ 'all' ] ) {
* @since 3.4
*
* @param array $domains Domain names to DNS prefetch.
*
* @return array
*/
public function add_dns_prefetch_cdn( $domains ) {
Expand All @@ -176,8 +181,9 @@ public function add_dns_prefetch_cdn( $domains ) {
*
* @since 3.4
*
* @param string $url URL to rewrite.
* @param string $url URL to rewrite.
* @param string $original_url Original URL for this URL. Optional.
*
* @return string
*/
public function add_cdn_url( $url, $original_url = '' ) {
Expand All @@ -195,8 +201,9 @@ public function add_cdn_url( $url, $original_url = '' ) {
*
* @since 3.5.3
*
* @param string $url URL of the asset.
* @param string $url URL of the asset.
* @param array $zones Array of corresponding zones for the asset.
*
* @return string
*/
public function maybe_replace_url( $url, array $zones = [ 'all' ] ) {
Expand Down Expand Up @@ -241,6 +248,69 @@ public function maybe_replace_url( $url, array $zones = [ 'all' ] ) {
return $url;
}

/**
* Add a preconnect tag for the CDN.
*
* @since 3.8.3
*
* @param array $urls The initial array of wp_resource_hint urls.
* @param string $relation_type The relation type for the hint: eg., 'preconnect', 'prerender', etc.
*
* @return array The filtered urls.
*/
public function add_preconnect_cdn( array $urls, string $relation_type ): array {
if (
'preconnect' !== $relation_type
||
rocket_bypass()
||
! $this->is_allowed()
||
! $this->is_cdn_enabled()
) {
return $urls;
}

$cdn_urls = $this->cdn->get_cdn_urls( [ 'all', 'images', 'css_and_js', 'css', 'js' ] );

if ( empty( $cdn_urls ) ) {
return $urls;
}

foreach ( $cdn_urls as $url ) {
$url_parts = get_rocket_parse_url( $url );

if ( empty( $url_parts['scheme'] ) ) {
if ( preg_match( '/^(?![\/])(?=[^\.]+\/).+/i', $url ) ) {
continue;
}

$url = '//' . $url;
$url_parts = get_rocket_parse_url( $url );
}

$domain = empty( $url_parts['scheme'] )
? '//' . $url_parts['host']
: $url_parts['scheme'] . '://' . $url_parts['host'];

// Note: As of 22 Feb, 2021 we cannot add more than one instance of a domain url
// on the wp_resource_hint() hook -- wp_resource_hint() will
// only actually print the first one.
// Ideally, we want both because CSS resources will use the crossorigin version,
// But JS resources will not.
// Jonathan has submitted a ticket to change this behavior:
// @see https://core.trac.wordpress.org/ticket/52465
// Until then, we order these to prefer/print the non-crossorigin version.
$urls[] = [ 'href' => $domain ];
$urls[] = [
'href' => $domain,
'crossorigin' => 'anonymous',
];
}

return $urls;
}

/**
* Checks if CDN can be applied
*
Expand Down
23 changes: 23 additions & 0 deletions tests/Fixtures/inc/Engine/CDN/Subscriber/add-preconnect-cdn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

return [
'shouldAddPreconnectLinkForCdn' => [
'cdn-cnames' => [
'123456.rocketcdn.me',
'https://my-cdn.cdnservice.com/',
'http://cdn.example.com',
'/some/path/with/no/domain',
'test/tests',
'8901.wicked-fast-cdn.com/path/to/my/files',
'https://another.cdn.com/with/a/path',
],
'expected-html' => <<<HTML
<link rel='dns-prefetch' href='//s.w.org' />
<link href='//123456.rocketcdn.me' rel='preconnect' />
<link href='https://my-cdn.cdnservice.com' rel='preconnect' />
<link href='http://cdn.example.com' rel='preconnect' />
<link href='//8901.wicked-fast-cdn.com' rel='preconnect' />
<link href='https://another.cdn.com' rel='preconnect' />
HTML
],
];
2 changes: 1 addition & 1 deletion tests/Integration/inc/Engine/CDN/Subscriber/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace WP_Rocket\Tests\Integration\inc\Engine\CDN\Subscriber;

use WPMedia\PHPUnit\Integration\TestCase as BaseTestCase;
use WP_Rocket\Tests\Integration\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase {
protected $cnames;
Expand Down
45 changes: 45 additions & 0 deletions tests/Integration/inc/Engine/CDN/Subscriber/addPreconnectCdn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace WP_Rocket\Tests\Integration\inc\Engine\CDN\Subscriber;

/**
* @covers \WP_Rocket\Engine\CDN\Subscriber::add_preconnect_cdn
* @uses \WP_Rocket\Engine\CDN\CDN::get_cdn_urls
* @group CDN
*/
class Test_addPreconnectCdn extends TestCase {

public function setUp() {
$this->unregisterAllCallbacksExcept( 'wp_resource_hints', 'add_preconnect_cdn', 10 );

parent::setUp();
}

public function tearDown() {
$this->restoreWpFilter( 'wp_resource_hints' );

parent::tearDown();
}

/**
* @dataProvider providerTestData
*/
public function testShouldAddPreconnectCdn($cnames, $expected) {
$this->cnames = $cnames;

add_filter( 'pre_get_rocket_option_cdn', [ $this, 'return_true'] );
add_filter( 'rocket_cdn_cnames', [ $this, 'setCnames' ] );

ob_start();
wp_resource_hints();

$this->assertSame(
$this->format_the_html($expected),
$this->format_the_html(ob_get_clean())
);
}

public function providerTestData() {
return $this->getTestData( __DIR__, 'add-preconnect-cdn' );
}
}

0 comments on commit bcc54d0

Please sign in to comment.