-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a warning when Cloudflare blocks REST API requests #8640
Conversation
lib/compat.php
Outdated
<p><?php _e( 'Your site uses Cloudflare, which provides a Web Application Firewall (WAF) to secure your site against attacks. Unfortunately, some of these WAF rules are incorrectly blocking legitimate access to your site, preventing Gutenberg from functioning correctly.', 'gutenberg' ); ?></p> | ||
<p><?php _e( "We're working closely with Cloudflare to fix this issue, but in the mean time, you can work around it in one of two ways:", 'gutenberg' ); ?></p> | ||
<ul> | ||
<li><?php _e( 'If you have a Cloudflare Pro account, login to Cloudflare, visit the Firewall settings page, open the "Cloudflare Rule Set" details, open the "Cloudflare WordPress" ruleset, then set the rules "WP0025A" and "WP0025A" to "Disable".', 'gutenberg' ); ?></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"WP0025A" and "WP0025A"
- the same id is listed twice.
If I follow the description of the PR right, it should be "WP0025A" and "WP0025B"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
packages/api-fetch/src/index.js
Outdated
@@ -68,16 +76,24 @@ function apiFetch( options ) { | |||
throw invalidJsonError; | |||
} | |||
|
|||
const responseClone = response.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unit test fails with the following message:
[TypeError: r[1] esponse.clone is not a function]
I bet you need to mock it because it is a part of the response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
packages/api-fetch/src/index.js
Outdated
@@ -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 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe:
typeof error === 'string'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
It works as advertised. I would personally consider wrapping those setting names and errors codes like When I edit post in Gutenberg and try to save it as draft I can see the notice, but when I click link to learn more I see need to accept dialog informing that my changes weren't saved. It would be great to tweak it to ensure that everyone easily navigates to the Classic Editor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that current implementation only show noticed when you try to update the status of the post. However there are many more cases when it can fail like:
- fetching taxonomies
- fetching authors
- dynamic blocks (latest posts, categories, ...)
And probably many more.
Yeah, I was originally looking at implementing it for all requests (1bd7f2a). There were a couple of problems with this approach:
So, I went with the post save action as being a reasonable tradeoff, where the user should notice the message when the first autosave happens, before they've really got into writing anything. |
@youknowriad implemented plugins API for When you visit Gutenberg for the first time, Document sidebar is expanded. This means it will trigger network requests for taxonomies and authors. You should be able to display a notice for Cloudflare users almost immediately. This would mitigate another concern I shared in the PR that you need to accept a dialog before you navigate away. |
lib/compat.php
Outdated
<p><?php _e( 'Your site uses Cloudflare, which provides a Web Application Firewall (WAF) to secure your site against attacks. Unfortunately, some of these WAF rules are incorrectly blocking legitimate access to your site, preventing Gutenberg from functioning correctly.', 'gutenberg' ); ?></p> | ||
<p><?php _e( "We're working closely with Cloudflare to fix this issue, but in the mean time, you can work around it in one of two ways:", 'gutenberg' ); ?></p> | ||
<ul> | ||
<li><?php _e( 'If you have a Cloudflare Pro account, login to Cloudflare, visit the Firewall settings page, open the "Cloudflare Rule Set" details, open the "Cloudflare WordPress" ruleset, then set the rules "WP0025A" and "WP0025B" to "Disable".', 'gutenberg' ); ?></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar: As a verb, the correct usage is "log in" as two words.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Core handbook also says to use "log in": https://make.wordpress.org/core/handbook/best-practices/spelling/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
packages/api-fetch/src/index.js
Outdated
@@ -68,16 +76,24 @@ function apiFetch( options ) { | |||
throw invalidJsonError; | |||
} | |||
|
|||
const responseClone = response.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to clone the response? (Add as an inline code comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
'cloudflare-error': '', | ||
} ); | ||
|
||
const cloudflaredMessage = error && 'cloudflare_error' === error.code ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: cloudflared
=> cloudflare
Edit: Or... intentional? I guess?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intentional, the reason for this even needing to exist is silly, and given that it'll (hopefully) be reverted next week, we can be a little silly with the variable names, too.
</p> : | ||
noticeMessage; | ||
|
||
dispatch( createErrorNotice( cloudflaredMessage, { id: SAVE_POST_NOTICE_ID } ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not loving how non-isolated the Cloudflare behaviors are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, but as I mentioned above, this is super temporary, it'll disappear before too long.
packages/api-fetch/src/index.js
Outdated
return response.json() | ||
.catch( () => { | ||
throw invalidJsonError; | ||
return responseClone.text() | ||
.then( ( text ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: Async/Await could make this nicer to read:
.catch( async () => {
const text = await responseClone.text();
checkCloudflareError( text );
throw invalidJsonError;
} );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
lib/compat.php
Outdated
<li> | ||
<?php | ||
printf( | ||
/* translators: link to a comment in the Gutenberg repo */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be /* translators: %s: link to a comment in the Gutenberg GitHub repository */
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
lib/compat.php
Outdated
<p> | ||
<?php | ||
printf( | ||
/* translators: link to an issue in the Gutenberg repo */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again missing the %s
in the comment + I wouldn't shorten repository here.
/* translators: %s: link to an issue in the Gutenberg GitHub repository */
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
I've fixed all the little things that needed to be fixed, but I haven't tried to re-architect it to catch all API requests. I also haven't fixed the "unsaved changes" dialog appearing, I guess we could do something to It's kind of hacky, and not ideal, but hopefully it'll be reverted by this time next week, so I'm not too concerned. 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's get it in. It is much better then it was before. Given that we hope to remove it before 3.6 gets out, I'm fine with the current proposal. Tested again, still works as intended.
Is it still needed? Where can I follow progress on the removal of this code? |
Description
When Cloudflare blocks REST API requests, there's nothing in the UI to suggest what the cause is, which is a confusing and frustrating experience.
Adding extra information when we detect the error helps folks determine their best course of action.
This is a temporary measure, to help with issues like #2704, until Cloudflare roll out their fix. As such, the message box is a fairly lazy copy/paste of the existing block warning in the Classic Editor.
How has this been tested?
With Cloudflare:
WP0003
andWP0004
, to ensure you're not being whitelisted.WP0025A
andWP0025B
.On your local site, you can simulate the REST API being blocked by Cloudflare with this snippet:
Screenshots
Clicking Learn More will redirect you to the Classic Editor, showing this message:
Checklist: