From 1bd7f2a6a4445f4610f7188f882c6d22c58b8344 Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 10:32:13 +1000 Subject: [PATCH 01/14] Catch a Cloudflare response, and redirect to the Classic editor.. --- packages/api-fetch/src/index.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index d8d669841bc8d..a40cc34be07bd 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -78,6 +79,16 @@ function apiFetch( options ) { message: __( 'An unknown error occurred.' ), }; + if ( error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { + window.location.href = addQueryArgs( + window.location.href, + { + 'classic-editor': '', + 'cloudflare-error': '', + } + ); + } + throw error || unknownError; } ); } ); From 6148a0577374b320c2494a793e06c713c2b33f5c Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 11:28:37 +1000 Subject: [PATCH 02/14] Ensure the url package is loaded when api-fetch needs it. --- lib/client-assets.php | 2 +- packages/api-fetch/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 0dfce73ab9f28..23aaa9a363d93 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -139,7 +139,7 @@ function gutenberg_register_scripts_and_styles() { wp_register_script( 'wp-api-fetch', gutenberg_url( 'build/api-fetch/index.js' ), - array( 'wp-hooks', 'wp-i18n' ), + array( 'wp-hooks', 'wp-i18n', 'wp-url' ), filemtime( gutenberg_dir_path() . 'build/api-fetch/index.js' ), true ); diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index 465e95da203bc..a8d84ff869eec 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -22,7 +22,8 @@ "dependencies": { "@babel/runtime": "^7.0.0-beta.52", "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n" + "@wordpress/i18n": "file:../i18n", + "@wordpress/url": "file:../url" }, "publishConfig": { "access": "public" From b8af9ea5243c3d04692fcf12c9a9e5070e0ec6f4 Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 11:29:06 +1000 Subject: [PATCH 03/14] Show a message in the Classic Editor when we redirect there from a Cloudflare block. --- lib/compat.php | 143 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 2 deletions(-) diff --git a/lib/compat.php b/lib/compat.php index e91a52b7036c9..0ddfea68ea2b7 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -167,7 +167,7 @@ function gutenberg_check_if_classic_needs_warning_about_blocks() { return; } - if ( ! gutenberg_post_has_blocks( $post ) ) { + if ( ! gutenberg_post_has_blocks( $post ) && ! isset( $_REQUEST['cloudflare-error'] ) ) { return; } @@ -175,7 +175,11 @@ function gutenberg_check_if_classic_needs_warning_about_blocks() { wp_enqueue_script( 'wp-a11y' ); wp_enqueue_script( 'wp-sanitize' ); - add_action( 'admin_footer', 'gutenberg_warn_classic_about_blocks' ); + if ( isset( $_REQUEST['cloudflare-error'] ) ) { + add_action( 'admin_footer', 'gutenberg_warn_classic_about_cloudflare' ); + } else { + add_action( 'admin_footer', 'gutenberg_warn_classic_about_blocks' ); + } } add_action( 'admin_enqueue_scripts', 'gutenberg_check_if_classic_needs_warning_about_blocks' ); @@ -322,3 +326,138 @@ function gutenberg_warn_classic_about_blocks() { + + +
+
+
+
+

+

+

+
    +
  • +
  • + change the REST API URL, to avoid triggering the WAF rules. Please be aware that this may cause issues with other plugins that use the REST API, and removes any other protection Cloudflare may be offering for the REST API.', 'gutenberg' ), + 'https://github.com/WordPress/gutenberg/issues/2704#issuecomment-410582252' + ); + ?> +
  • +
+

+ follow this issue for updates. We hope to have this issue rectifed soon!', 'gutenberg' ), + 'https://github.com/WordPress/gutenberg/issues/2704' + ); + ?> +

+
+

+ +

+
+
+ + + Date: Tue, 7 Aug 2018 13:02:34 +1000 Subject: [PATCH 04/14] Don't auto-redirect to Classic, give a link, instead. --- lib/client-assets.php | 2 +- packages/api-fetch/package.json | 3 +-- packages/api-fetch/src/index.js | 27 +++++++++++++--------- packages/editor/src/store/effects/posts.js | 23 +++++++++++++++++- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/lib/client-assets.php b/lib/client-assets.php index 23aaa9a363d93..0dfce73ab9f28 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -139,7 +139,7 @@ function gutenberg_register_scripts_and_styles() { wp_register_script( 'wp-api-fetch', gutenberg_url( 'build/api-fetch/index.js' ), - array( 'wp-hooks', 'wp-i18n', 'wp-url' ), + array( 'wp-hooks', 'wp-i18n' ), filemtime( gutenberg_dir_path() . 'build/api-fetch/index.js' ), true ); diff --git a/packages/api-fetch/package.json b/packages/api-fetch/package.json index a8d84ff869eec..465e95da203bc 100644 --- a/packages/api-fetch/package.json +++ b/packages/api-fetch/package.json @@ -22,8 +22,7 @@ "dependencies": { "@babel/runtime": "^7.0.0-beta.52", "@wordpress/hooks": "file:../hooks", - "@wordpress/i18n": "file:../i18n", - "@wordpress/url": "file:../url" + "@wordpress/i18n": "file:../i18n" }, "publishConfig": { "access": "public" diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index a40cc34be07bd..4ca51eafa8380 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -19,6 +18,14 @@ function registerMiddleware( middleware ) { middlewares.push( middleware ); } +function checkCloudflareError( error ) { + if ( error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { + throw { + code: 'cloudflare_error', + }; + } +} + function apiFetch( options ) { const raw = ( nextOptions ) => { const { url, path, body, data, parse = true, ...remainingOptions } = nextOptions; @@ -69,9 +76,15 @@ function apiFetch( options ) { throw invalidJsonError; } + const responseClone = response.clone(); + return response.json() .catch( () => { - throw invalidJsonError; + return responseClone.text() + .then( ( text ) => { + checkCloudflareError( text ); + throw invalidJsonError; + } ); } ) .then( ( error ) => { const unknownError = { @@ -79,15 +92,7 @@ function apiFetch( options ) { message: __( 'An unknown error occurred.' ), }; - if ( error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { - window.location.href = addQueryArgs( - window.location.href, - { - 'classic-editor': '', - 'cloudflare-error': '', - } - ); - } + checkCloudflareError( error ); throw error || unknownError; } ); diff --git a/packages/editor/src/store/effects/posts.js b/packages/editor/src/store/effects/posts.js index 9b541cafc5ade..8062916166188 100644 --- a/packages/editor/src/store/effects/posts.js +++ b/packages/editor/src/store/effects/posts.js @@ -9,6 +9,7 @@ import { pick, includes } from 'lodash'; */ import apiFetch from '@wordpress/api-fetch'; import { __ } from '@wordpress/i18n'; +import { addQueryArgs } from '@wordpress/url'; /** * Internal dependencies @@ -256,7 +257,27 @@ export const requestPostUpdateFailure = ( action, store ) => { const noticeMessage = ! isPublished && publishStatus.indexOf( edits.status ) !== -1 ? messages[ edits.status ] : __( 'Updating failed' ); - dispatch( createErrorNotice( noticeMessage, { id: SAVE_POST_NOTICE_ID } ) ); + + const cloudflareDetailsLink = addQueryArgs( + 'post.php', + { + post: post.id, + action: 'edit', + 'classic-editor': '', + 'cloudflare-error': '', + } ); + + const cloudflaredMessage = error && 'cloudflare_error' === error.code ? +

+ { noticeMessage } +
+ { __( 'Cloudflare is blocking REST API requests.' ) } + { ' ' } + { __( 'Learn More' ) } +

: + noticeMessage; + + dispatch( createErrorNotice( cloudflaredMessage, { id: SAVE_POST_NOTICE_ID } ) ); }; /** From d41f6582093d8ba8cc3b60f946bf41295d0be44b Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 13:39:11 +1000 Subject: [PATCH 05/14] Linting. --- lib/compat.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compat.php b/lib/compat.php index 0ddfea68ea2b7..04dd139c625c1 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -368,8 +368,8 @@ function gutenberg_warn_classic_about_cloudflare() {
  • change the REST API URL, to avoid triggering the WAF rules. Please be aware that this may cause issues with other plugins that use the REST API, and removes any other protection Cloudflare may be offering for the REST API.', 'gutenberg' ), 'https://github.com/WordPress/gutenberg/issues/2704#issuecomment-410582252' ); @@ -378,8 +378,8 @@ function gutenberg_warn_classic_about_cloudflare() {

    follow this issue for updates. We hope to have this issue rectifed soon!', 'gutenberg' ), 'https://github.com/WordPress/gutenberg/issues/2704' ); From 8c384cc9424a3f67295e2b22664da8db8c4ab5de Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 13:41:16 +1000 Subject: [PATCH 06/14] Pinking shears --- packages/editor/src/store/effects/posts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/store/effects/posts.js b/packages/editor/src/store/effects/posts.js index 8062916166188..46ddaa04374fe 100644 --- a/packages/editor/src/store/effects/posts.js +++ b/packages/editor/src/store/effects/posts.js @@ -267,7 +267,7 @@ export const requestPostUpdateFailure = ( action, store ) => { 'cloudflare-error': '', } ); - const cloudflaredMessage = error && 'cloudflare_error' === error.code ? + const cloudflaredMessage = error && 'cloudflare_error' === error.code ?

    { noticeMessage }
    From 4ad8095baac420f09059937a33fc746aab5467a9 Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 14:51:23 +1000 Subject: [PATCH 07/14] Fix the incorrect Cloudflare rule ID being listed. --- lib/compat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat.php b/lib/compat.php index 04dd139c625c1..b1611c9cf7e23 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -365,7 +365,7 @@ function gutenberg_warn_classic_about_cloudflare() {

      -
    • +
    • Date: Tue, 7 Aug 2018 15:10:19 +1000 Subject: [PATCH 08/14] Mock Resonse.clone() in the tests. --- packages/api-fetch/src/test/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/api-fetch/src/test/index.js b/packages/api-fetch/src/test/index.js index 4e940e18233ef..47aa4d2303e14 100644 --- a/packages/api-fetch/src/test/index.js +++ b/packages/api-fetch/src/test/index.js @@ -32,6 +32,9 @@ describe( 'apiFetch', () => { message: 'Bad Request', } ); }, + clone() { + return null; + }, } ) ); return apiFetch( { path: '/random' } ).catch( ( body ) => { From 9191016d06e584ddb7c41215f9676eab71da46fb Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 7 Aug 2018 15:10:40 +1000 Subject: [PATCH 09/14] Make checkCloudflareError() more resilient to non-strings being passed to it. --- packages/api-fetch/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index 4ca51eafa8380..bca5cb7cceccd 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -19,7 +19,7 @@ function registerMiddleware( middleware ) { } function checkCloudflareError( error ) { - if ( error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { + if ( error.indexOf && error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { throw { code: 'cloudflare_error', }; From 2219590d4c7f1c92a79dcf257349ca4763bf191a Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Wed, 8 Aug 2018 17:18:14 +1000 Subject: [PATCH 10/14] Use typeof instead of checking for .indexOf on the error to check that it's a string. --- packages/api-fetch/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index bca5cb7cceccd..0aff848772b54 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -19,7 +19,7 @@ function registerMiddleware( middleware ) { } function checkCloudflareError( error ) { - if ( error.indexOf && error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { + if ( typeof error === 'string' && error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) { throw { code: 'cloudflare_error', }; From fbe7d6fd41b0b3a9bf96181d455585c0d2c2734d Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Wed, 8 Aug 2018 17:19:58 +1000 Subject: [PATCH 11/14] s/login/log in/ --- lib/compat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compat.php b/lib/compat.php index b1611c9cf7e23..ca57c1d66bcb0 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -365,7 +365,7 @@ function gutenberg_warn_classic_about_cloudflare() {

        -
      • +
      • Date: Wed, 8 Aug 2018 17:20:07 +1000 Subject: [PATCH 12/14] Improve translator comments. --- lib/compat.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compat.php b/lib/compat.php index ca57c1d66bcb0..7532dd2ebcfff 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -369,7 +369,7 @@ function gutenberg_warn_classic_about_cloudflare() {
      • change the REST API URL, to avoid triggering the WAF rules. Please be aware that this may cause issues with other plugins that use the REST API, and removes any other protection Cloudflare may be offering for the REST API.', 'gutenberg' ), 'https://github.com/WordPress/gutenberg/issues/2704#issuecomment-410582252' ); @@ -379,7 +379,7 @@ function gutenberg_warn_classic_about_cloudflare() {

        follow this issue for updates. We hope to have this issue rectifed soon!', 'gutenberg' ), 'https://github.com/WordPress/gutenberg/issues/2704' ); From 9c7001945a66e863b710825930be1d12b66ec113 Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Wed, 8 Aug 2018 17:21:34 +1000 Subject: [PATCH 13/14] Improve readability of the JSON parsing error handling --- packages/api-fetch/src/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index 0aff848772b54..2f11e07765e93 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -79,12 +79,10 @@ function apiFetch( options ) { const responseClone = response.clone(); return response.json() - .catch( () => { - return responseClone.text() - .then( ( text ) => { - checkCloudflareError( text ); - throw invalidJsonError; - } ); + .catch( async () => { + const text = await responseClone.text(); + checkCloudflareError( text ); + throw invalidJsonError; } ) .then( ( error ) => { const unknownError = { From 468d0240fae0ba8394a184092375c4e8c8f36f3d Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Wed, 8 Aug 2018 17:24:42 +1000 Subject: [PATCH 14/14] Add a comment explaining why the response is being cloned. --- packages/api-fetch/src/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/api-fetch/src/index.js b/packages/api-fetch/src/index.js index 2f11e07765e93..a2ebeeff37a9a 100644 --- a/packages/api-fetch/src/index.js +++ b/packages/api-fetch/src/index.js @@ -76,6 +76,12 @@ function apiFetch( options ) { throw invalidJsonError; } + /* + * Response data is a stream, which will be consumed by the .json() call. + * If we need to re-use this data to send to the Cloudflare error handler, + * we need a clone of the original response, so the stream can be consumed + * in the .text() call, instead. + */ const responseClone = response.clone(); return response.json()