From dae86c41dbcabdbd95d0f1076c2b9685242df0be Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Mon, 22 Feb 2021 16:22:15 -0500 Subject: [PATCH 1/9] Refactor client-hints, add Permissions-Policy --- imageengine/class-imagecdn.php | 51 ++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index 11ade71..b6561a8 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -20,6 +20,20 @@ public static function instance() { new self(); } + /** + * Client hints. + */ + private static $client_hints = array( + 'Viewport-Width', + 'Width', + 'DPR', + 'ECT', + // Disabled for CORS compatibility + // 'Device-Memory', + // 'RTT', + // 'Downlink', + ); + /** * Singleton Rewriter instance * @@ -41,7 +55,7 @@ public function __construct() { add_filter( 'the_content', array( self::class, 'rewrite_html' ), 100 ); // Resource hints. Note that the 'wp_head' is disabled for the time being due to CORS incompatibility. - // add_action( 'wp_head', array( self::class, 'add_head_tags' ), 0 ); . + // add_action( 'wp_head', array( self::class, 'add_head_tags' ), 0 ); add_action( 'send_headers', array( self::class, 'add_headers' ), 0 ); // REST API hooks. @@ -65,17 +79,38 @@ public function __construct() { * Add http headers for Client Hints, Feature Policy and Preconnect Resource Hint. */ public static function add_headers() { - // Add client hints. - header( 'Accept-CH: viewport-width, width, device-memory, dpr, downlink, ect' ); + + header( 'Accept-CH: ' . strtolower( implode( ', ', self::$client_hints ) ) ); // Add resource hints and feature policy. $options = self::get_options(); $host = wp_parse_url( $options['url'], PHP_URL_HOST ); - if ( ! empty( $host ) ) { - $protocol = ( is_ssl() ) ? 'https://' : 'http://'; - header( 'Link: <' . $protocol . $host . '>; rel=preconnect' ); - header( 'Feature-Policy: ch-viewport-width ' . $protocol . $host . '; ch-width ' . $protocol . $host . '; ch device-memory ' . $protocol . $host . '; ch-dpr ' . $protocol . $host . '; ch-downlink ' . $protocol . $host . '; ch-ect ' . $protocol . $host . ';' ); + if ( empty( $host ) ) { + return; + } + + $protocol = is_ssl() ? 'https' : 'http'; + + // Add Preconnect header + header( "Link: <${protocol}://${host}>; rel=preconnect" ); + + // Add Feature-Policy header. + // @deprecated in favor of Permissions-Policy and will be removed once adaquate market + // adoption has been reached (90-95%). + $features = array(); + foreach ( self::$client_hints as $hint ) { + $features[] = strtolower( "ch-${hint} ${protocol}://${host}" ); + } + header( 'Feature-Policy: ' . strtolower( implode( '; ', $features ) ) ); + + $permissions = array(); + foreach (self::$client_hints as $hint) { + $permissions[] = strtolower( "ch-${hint}=(${protocol}://${host})" ); } + // Add Permissions-Policy header. + // This header replaced Feature-Policy in Chrome 88, released in January 2021. + // @see https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md#appendix-big-changes-since-this-was-called-feature-policy + header( 'Permissions-Policy: ' . strtolower( implode( ', ', $permissions ) ) ); } @@ -84,7 +119,7 @@ public static function add_headers() { */ public static function add_head_tags() { // Add client hints. - echo ' ' . "\n"; + echo ' ' . "\n"; // Add resource hints. $options = self::get_options(); From 296e7211e7273a09cbf08734ff51854eb0122cf1 Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Mon, 22 Feb 2021 17:08:35 -0500 Subject: [PATCH 2/9] Added unit tests for CH headers --- imageengine/class-imagecdn.php | 43 +++++++++++++++++++++++++++++----- tests/standalone/bootstrap.php | 8 +++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index b6561a8..47b1880 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -1,6 +1,6 @@ ; rel=preconnect" ); + self::header( 'Link', "<${protocol}://${host}>; rel=preconnect" ); // Add Feature-Policy header. // @deprecated in favor of Permissions-Policy and will be removed once adaquate market @@ -101,7 +129,7 @@ public static function add_headers() { foreach ( self::$client_hints as $hint ) { $features[] = strtolower( "ch-${hint} ${protocol}://${host}" ); } - header( 'Feature-Policy: ' . strtolower( implode( '; ', $features ) ) ); + self::header( 'Feature-Policy', strtolower( implode( '; ', $features ) ) ); $permissions = array(); foreach (self::$client_hints as $hint) { @@ -110,7 +138,7 @@ public static function add_headers() { // Add Permissions-Policy header. // This header replaced Feature-Policy in Chrome 88, released in January 2021. // @see https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md#appendix-big-changes-since-this-was-called-feature-policy - header( 'Permissions-Policy: ' . strtolower( implode( ', ', $permissions ) ) ); + self::header( 'Permissions-Policy', strtolower( implode( ', ', $permissions ) ) ); } @@ -303,6 +331,9 @@ public static function register_textdomain() { * @return array $diff data pairs. */ public static function get_options() { + if ( self::$tests_running ) { + return self::$test_options; + } return wp_parse_args( get_option( 'image_cdn' ), self::default_options() ); } diff --git a/tests/standalone/bootstrap.php b/tests/standalone/bootstrap.php index 41f861c..3beb92e 100644 --- a/tests/standalone/bootstrap.php +++ b/tests/standalone/bootstrap.php @@ -17,3 +17,11 @@ function is_admin_bar_showing() { return false; } + +function wp_parse_url($url, $flags) { + return parse_url($url, $flags); +} + +function is_ssl() { + return true; +} \ No newline at end of file From dfc60410d8793ec2b0a24227e8b118ef28741e07 Mon Sep 17 00:00:00 2001 From: Jon Arne S Date: Tue, 23 Feb 2021 12:30:29 +0100 Subject: [PATCH 3/9] added " in header values --- imageengine/class-imagecdn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index 47b1880..3eaf89e 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -133,7 +133,7 @@ public static function add_headers() { $permissions = array(); foreach (self::$client_hints as $hint) { - $permissions[] = strtolower( "ch-${hint}=(${protocol}://${host})" ); + $permissions[] = strtolower( "ch-${hint}=(\"${protocol}://${host}\")" ); } // Add Permissions-Policy header. // This header replaced Feature-Policy in Chrome 88, released in January 2021. From 430f9caf89019750e654a3fb92a303098eaa4615 Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Tue, 23 Feb 2021 10:31:09 -0500 Subject: [PATCH 4/9] Added standalone test for headers --- tests/standalone/test-imagecdn.php | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/standalone/test-imagecdn.php diff --git a/tests/standalone/test-imagecdn.php b/tests/standalone/test-imagecdn.php new file mode 100644 index 0000000..d5d70e5 --- /dev/null +++ b/tests/standalone/test-imagecdn.php @@ -0,0 +1,32 @@ + 'https://foo.com', + ]; + + ImageCDN::add_headers(); + + $expected = [ + 'Accept-CH: viewport-width, width, dpr, ect', + 'Link: ; rel=preconnect', + 'Feature-Policy: ch-viewport-width https://foo.com; ch-width https://foo.com; ch-dpr https://foo.com; ch-ect https://foo.com', + 'Permissions-Policy: ch-viewport-width=("https://foo.com"), ch-width=("https://foo.com"), ch-dpr=("https://foo.com"), ch-ect=("https://foo.com")', + ]; + $this->assertSame($expected, ImageCDN::$test_headers_written); + } +} \ No newline at end of file From c039b76a7563c4a6dfe9b063c0406bd75e6fd774 Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Tue, 23 Feb 2021 10:49:45 -0500 Subject: [PATCH 5/9] Fixed variable interpolation syntax --- imageengine/class-imagecdn.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index 3eaf89e..2ad0409 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -120,20 +120,20 @@ public static function add_headers() { $protocol = is_ssl() ? 'https' : 'http'; // Add Preconnect header - self::header( 'Link', "<${protocol}://${host}>; rel=preconnect" ); + self::header( 'Link', "<{$protocol}://{$host}>; rel=preconnect" ); // Add Feature-Policy header. // @deprecated in favor of Permissions-Policy and will be removed once adaquate market // adoption has been reached (90-95%). $features = array(); foreach ( self::$client_hints as $hint ) { - $features[] = strtolower( "ch-${hint} ${protocol}://${host}" ); + $features[] = strtolower( "ch-{$hint} {$protocol}://{$host}" ); } self::header( 'Feature-Policy', strtolower( implode( '; ', $features ) ) ); $permissions = array(); foreach (self::$client_hints as $hint) { - $permissions[] = strtolower( "ch-${hint}=(\"${protocol}://${host}\")" ); + $permissions[] = strtolower( "ch-{$hint}=(\"{$protocol}://{$host}\")" ); } // Add Permissions-Policy header. // This header replaced Feature-Policy in Chrome 88, released in January 2021. From 491559bb44ef94d20d38fdab095cdb7c60846d1d Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Tue, 23 Feb 2021 10:59:45 -0500 Subject: [PATCH 6/9] Updated code to pass WP coding standards --- Makefile | 17 +++++++++++---- imageengine/class-imagecdn.php | 39 ++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 124b479..24784fb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: % dist-clean dist make-zip svn +.PHONY: % dist-clean dist make-zip svn test check fix FILE := image-cdn-0.0.0.zip @@ -14,6 +14,15 @@ make-zip: cd dist && zip -9 -r ${FILE} image_cdn rm -rf dist/image_cdn -svn: - cp -v -r plugin-assets/* svn/assets/ - cp -v -r *.php *.txt imageengine assets templates svn/trunk +test: + vendor/bin/phpunit -vvv -c phpunit-standalone.xml.dist + +fix: + vendor/bin/phpcbf -v + +check: + vendor/bin/phpcs + +# svn: +# cp -v -r plugin-assets/* svn/assets/ +# cp -v -r *.php *.txt imageengine assets templates svn/trunk diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index 2ad0409..1dc37df 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -22,16 +22,20 @@ public static function instance() { /** * Client hints. + * + * @var []string */ private static $client_hints = array( 'Viewport-Width', 'Width', 'DPR', 'ECT', - // Disabled for CORS compatibility - // 'Device-Memory', - // 'RTT', - // 'Downlink', + /** + * Disabled for CORS compatibility: + * 'Device-Memory', + * 'RTT', + * 'Downlink', + */ ); /** @@ -43,16 +47,25 @@ public static function instance() { /** * If true, some functionality will be augmented to facilitate testing. + * + * @internal + * @var bool */ public static $tests_running = false; /** * Captures headers written during unit testing. + * + * @internal + * @var []string */ public static $test_headers_written = array(); /** * Options that will be used during unit testing. + * + * @internal + * @var []string */ public static $test_options = array(); @@ -69,8 +82,10 @@ public function __construct() { // Rewrite rendered content in REST API. add_filter( 'the_content', array( self::class, 'rewrite_html' ), 100 ); - // Resource hints. Note that the 'wp_head' is disabled for the time being due to CORS incompatibility. - // add_action( 'wp_head', array( self::class, 'add_head_tags' ), 0 ); + /** + * Resource hints. Note that the 'wp_head' is disabled for the time being due to CORS incompatibility. + * add_action( 'wp_head', array( self::class, 'add_head_tags' ), 0 ); + */ add_action( 'send_headers', array( self::class, 'add_headers' ), 0 ); // REST API hooks. @@ -92,6 +107,9 @@ public function __construct() { /** * Outputs an HTTP header. + * + * @param string $key HTTP header key. + * @param string $value HTTP header value. */ private static function header( $key, $value ) { $val = "$key: $value"; @@ -107,7 +125,6 @@ private static function header( $key, $value ) { * Add http headers for Client Hints, Feature Policy and Preconnect Resource Hint. */ public static function add_headers() { - self::header( 'Accept-CH', strtolower( implode( ', ', self::$client_hints ) ) ); // Add resource hints and feature policy. @@ -119,7 +136,7 @@ public static function add_headers() { $protocol = is_ssl() ? 'https' : 'http'; - // Add Preconnect header + // Add Preconnect header. self::header( 'Link', "<{$protocol}://{$host}>; rel=preconnect" ); // Add Feature-Policy header. @@ -132,12 +149,12 @@ public static function add_headers() { self::header( 'Feature-Policy', strtolower( implode( '; ', $features ) ) ); $permissions = array(); - foreach (self::$client_hints as $hint) { + foreach ( self::$client_hints as $hint ) { $permissions[] = strtolower( "ch-{$hint}=(\"{$protocol}://{$host}\")" ); } // Add Permissions-Policy header. // This header replaced Feature-Policy in Chrome 88, released in January 2021. - // @see https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md#appendix-big-changes-since-this-was-called-feature-policy + // @see https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md#appendix-big-changes-since-this-was-called-feature-policy . self::header( 'Permissions-Policy', strtolower( implode( ', ', $permissions ) ) ); } @@ -147,7 +164,7 @@ public static function add_headers() { */ public static function add_head_tags() { // Add client hints. - echo ' ' . "\n"; + echo ' ' . "\n"; // Add resource hints. $options = self::get_options(); From c80cf26aa5149feaf71ab1f4fefb05b5122dc80f Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Tue, 23 Feb 2021 15:24:32 -0500 Subject: [PATCH 7/9] Version bump --- image-cdn.php | 2 +- readme.txt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/image-cdn.php b/image-cdn.php index 2eff73d..e41a9ff 100644 --- a/image-cdn.php +++ b/image-cdn.php @@ -16,7 +16,7 @@ * Requires PHP: 5.6 * Text Domain: image-cdn * License: GPLv2 or later - * Version: 1.1.0 + * Version: 1.1.1 */ // Load plugin files. diff --git a/readme.txt b/readme.txt index f980703..ca8be73 100644 --- a/readme.txt +++ b/readme.txt @@ -120,6 +120,11 @@ Upgrades can be performed in the normal WordPress way, nothing else will need to == Changelog == += 1.1.1 = +* Improved CORS compatibility +* Removed downlink hint +* Added Permissions-Policy header + = 1.1.0 = * Fixed compatibility issue with Divi * Increased performance From 78e06cb0d04eed97cad75cd17f24b866caf8b42d Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Tue, 23 Feb 2021 16:28:25 -0500 Subject: [PATCH 8/9] Removed ch-ect, added version number to settings page, updated tests --- image-cdn.php | 7 ++++++- imageengine/class-imagecdn.php | 2 +- imageengine/class-rewriter.php | 9 ++++++++- readme.txt | 2 +- templates/settings.php | 18 +++++++++++++----- tests/standalone/test-imagecdn.php | 6 +++--- tests/standalone/test-rewriter.php | 8 +++++--- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/image-cdn.php b/image-cdn.php index e41a9ff..6b5c8e1 100644 --- a/image-cdn.php +++ b/image-cdn.php @@ -19,6 +19,12 @@ * Version: 1.1.1 */ +// Update this then you update "Requires at least" above! +define( 'IMAGE_CDN_MIN_WP', '4.6' ); + +// Update this when you update the "Version" above! +define( 'IMAGE_CDN_VERSION', '1.1.1' ); + // Load plugin files. require_once __DIR__ . '/imageengine/class-settings.php'; require_once __DIR__ . '/imageengine/class-rewriter.php'; @@ -29,7 +35,6 @@ define( 'IMAGE_CDN_FILE', __FILE__ ); define( 'IMAGE_CDN_DIR', __DIR__ ); define( 'IMAGE_CDN_BASE', plugin_basename( __FILE__ ) ); -define( 'IMAGE_CDN_MIN_WP', '3.8' ); add_action( 'plugins_loaded', array( ImageEngine\ImageCDN::class, 'instance' ) ); register_uninstall_hook( __FILE__, array( ImageEngine\ImageCDN::class, 'handle_uninstall_hook' ) ); diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index 1dc37df..605ce4f 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -29,9 +29,9 @@ public static function instance() { 'Viewport-Width', 'Width', 'DPR', - 'ECT', /** * Disabled for CORS compatibility: + * 'ECT', * 'Device-Memory', * 'RTT', * 'Downlink', diff --git a/imageengine/class-rewriter.php b/imageengine/class-rewriter.php index b63a511..ed6a9b5 100644 --- a/imageengine/class-rewriter.php +++ b/imageengine/class-rewriter.php @@ -115,12 +115,19 @@ public function __construct( * @return boolean true if need to be excluded. */ public function exclude_asset( $asset ) { + $path = strtolower( wp_parse_url( $asset, PHP_URL_PATH ) ); + // Excludes. foreach ( $this->excludes as $exclude ) { - if ( $exclude && stripos( $asset, $exclude ) !== false ) { + if ( '' === $exclude ) { + continue; + } + + if ( false !== strpos( $path, strtolower( $exclude ) ) ) { return true; } } + return false; } diff --git a/readme.txt b/readme.txt index ca8be73..0a00e6d 100644 --- a/readme.txt +++ b/readme.txt @@ -122,7 +122,7 @@ Upgrades can be performed in the normal WordPress way, nothing else will need to = 1.1.1 = * Improved CORS compatibility -* Removed downlink hint +* Removed downlink and ect hint * Added Permissions-Policy header = 1.1.0 = diff --git a/templates/settings.php b/templates/settings.php index 5df8e29..03740ef 100644 --- a/templates/settings.php +++ b/templates/settings.php @@ -18,11 +18,11 @@ ); ?>

-

:

+

  1. Sign up for an ImageEngine account
  2. -

    See full documentation.

    -

    +

    + +

    @@ -119,11 +127,11 @@

    - , + ,

    diff --git a/tests/standalone/test-imagecdn.php b/tests/standalone/test-imagecdn.php index d5d70e5..472307e 100644 --- a/tests/standalone/test-imagecdn.php +++ b/tests/standalone/test-imagecdn.php @@ -22,10 +22,10 @@ public function testAddHeaders() { ImageCDN::add_headers(); $expected = [ - 'Accept-CH: viewport-width, width, dpr, ect', + 'Accept-CH: viewport-width, width, dpr', 'Link: ; rel=preconnect', - 'Feature-Policy: ch-viewport-width https://foo.com; ch-width https://foo.com; ch-dpr https://foo.com; ch-ect https://foo.com', - 'Permissions-Policy: ch-viewport-width=("https://foo.com"), ch-width=("https://foo.com"), ch-dpr=("https://foo.com"), ch-ect=("https://foo.com")', + 'Feature-Policy: ch-viewport-width https://foo.com; ch-width https://foo.com; ch-dpr https://foo.com', + 'Permissions-Policy: ch-viewport-width=("https://foo.com"), ch-width=("https://foo.com"), ch-dpr=("https://foo.com")', ]; $this->assertSame($expected, ImageCDN::$test_headers_written); } diff --git a/tests/standalone/test-rewriter.php b/tests/standalone/test-rewriter.php index 0b1526c..7629c05 100644 --- a/tests/standalone/test-rewriter.php +++ b/tests/standalone/test-rewriter.php @@ -20,15 +20,17 @@ public function testExcludeAsset() { $cdn_url = 'http://my.cdn'; $path = ''; $dirs = 'wp-includes'; - $excludes = array( '.php' ); + $excludes = array( '.php', '.woff2' ); $relative = true; $https = true; $directives = '/cmpr_20'; $rewrite = new Rewriter( $blog_url, $cdn_url, $path, $dirs, $excludes, $relative, $https, $directives ); - $this->assertEquals( true, $rewrite->exclude_asset( '/wp-includes/bar.php' ) ); - $this->assertEquals( true, $rewrite->exclude_asset( '/wp-includes/bar.php/foo.jpg' ) ); + $this->assertEquals( true, $rewrite->exclude_asset( '/wp-includes/bar.php' ) ); + $this->assertEquals( true, $rewrite->exclude_asset( '/wp-includes/bar.woff2' ) ); + $this->assertEquals( false, $rewrite->exclude_asset( '/wp-includes/bar.woff' ) ); + $this->assertEquals( true, $rewrite->exclude_asset( '/wp-includes/bar.php/foo.jpg' ) ); $this->assertEquals( false, $rewrite->exclude_asset( '/wp-includes/bar.jpg' ) ); } From 7ab55d0dedd7b58aa762c414da45f3dc29d0834f Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Tue, 23 Feb 2021 16:59:00 -0500 Subject: [PATCH 9/9] Added prototype CORS config check --- imageengine/class-imagecdn.php | 39 ++++++++++++++++++++++++++++++++++ imageengine/class-settings.php | 26 +++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/imageengine/class-imagecdn.php b/imageengine/class-imagecdn.php index 605ce4f..72db95b 100644 --- a/imageengine/class-imagecdn.php +++ b/imageengine/class-imagecdn.php @@ -38,6 +38,17 @@ public static function instance() { */ ); + /** + * Client hints that do not require CORS preflight confirmation. + * + * @var []string + */ + private static $safe_client_hints = array( + 'Viewport-Width', + 'Width', + 'DPR', + ); + /** * Singleton Rewriter instance. * @@ -198,6 +209,34 @@ public static function add_action_link( $data ) { ); } + /** + * Gets the list of active client hints. + * + * @return array client hints. + */ + public static function get_client_hints() { + return self::$client_hints; + } + + /** + * Gets the list of safe client hints. + * + * @return array client hints. + */ + public static function get_safe_client_hints() { + return self::$safe_client_hints; + } + + /** + * Gets the list of active unsafe client hints. + * + * @return array client hints. + */ + public static function get_unsafe_client_hints() { + return array_diff( self::$client_hints, self::$safe_client_hints ); + } + + /** * Rewrite image URLs in REST API responses * diff --git a/imageengine/class-settings.php b/imageengine/class-settings.php index bfd7b3b..d2ef9b8 100644 --- a/imageengine/class-settings.php +++ b/imageengine/class-settings.php @@ -254,17 +254,39 @@ public static function test_config() { if ( ! isset( $cdn_res['headers']['content-type'] ) ) { $out['type'] = 'warning'; - $out['message'] = 'Unable to confirm that the CDN is working properly because it didn\'t send a content type'; + $out['message'] = 'Unable to confirm that the CDN is working properly because it didn\'t send Content-Type'; wp_send_json_error( $out ); } $cdn_type = $cdn_res['headers']['content-type']; if ( strpos( $cdn_type, 'image/png' ) === false ) { $out['type'] = 'error'; - $out['message'] = "CDN returned the wrong content type (expected 'image/png', got '$cdn_type'"; + $out['message'] = "CDN returned the wrong content type (expected 'image/png', got '$cdn_type')"; wp_send_json_error( $out ); } + /** + * This check it commented out until we can confirm that it properly tests CORS functionality. + * + * $unsafe_hints = ImageCDN::get_unsafe_client_hints(); + * if ( 0 < count( $unsafe_hints ) ) { + * $cors_error = true; + * if ( ! array_key_exists( 'access-control-allowed-headers', $cdn_res['headers'] ) ) { + * $out['type'] = 'warning'; + * $out['message'] = 'Unable to confirm that the CDN supports client-hints because it didn\'t send Access-Control-Allow-Headers. Fonts may not work if served from the CDN.'; + * wp_send_json_error( $out ); + * } + * + * $allowed = preg_split( '/ +/', trim( $cdn_res['headers']['access-control-allowed-headers'] ) ); + * $missing_hints = array_diff( $unsafe_hints, $allowed ); + * if ( 0 < count( $missing_hints ) ) { + * $out['type'] = 'warning'; + * $out['message'] = 'Unable to confirm that the CDN supports advanced client-hints because it is missing some active client-hints in Access-Control-Allow-Headers (' . implode( ',', $missing_hints ) . '). Fonts may not work if served from the CDN.'; + * wp_send_json_error( $out ); + * } + * } + */ + $out['type'] = 'success'; $out['message'] = 'Test successful'; wp_send_json_success( $out );