[Query API] Use the exact redirect URL provided in the ?url= query param#1945
Conversation
This PR:
* Replaces the `wp_redirect()` call with `header("Location: ")` to ensure
support for all valid redirection URLs.
* Adds a timeout before probing for the embedded Playground `iframe` URL
when the `load` event handler runs.
### Ditching `wp_redirect()`
The `wp_redirect()` call was introduced in #1856 to handle the post-autologin
redirect. Unfortunately, it strips valid sequences such as `%0A` and `%0D` from
the redirection URL. This isn't useful in Playground and breaks valid
use-cases such as using the `?url=` parameter to initialize `html-api-debugger`
with a valid HTML markup containing newlines.
### Timeout before probing `contentWindow.location.href`
When navigating to a page with %0A sequences (encoded newlines)
in the query string, the `location.href` property of the
iframe's content window doesn't seem to reflect them. Everything
else is in place, but not the %0A sequences.
Weirdly, these sequences are available after the next event
loop tick – hence the `setTimeout(0)`.
The exact cause is unclear to me. The WHATWG HTML Standard [1] has a few hints:
* Current and active session history entries may get out of
sync for iframes.
* Documents inside iframes have "is delaying load events" set
to true.
But there doesn't seem to be any concrete explanation and no
recommended remediation. If anyone has a clue, please share it
in a GitHub issue or start a new PR.
[1] https://html.spec.whatwg.org/multipage/document-sequences.html#nav-active-history-entry
## Testing instructions
CI tests aside, try this:
1. Go to http://localhost:5400/website-server/?plugin=html-api-debugger&url=%2Fwp-admin%2Fadmin.php%3Fpage%3Dhtml-api-debugger%26html%3D%253Cdiv%253E%250A1%250A2%250A3%250A%253C%252Fdiv%253E&wp=6.6&php=8.0&networking=no&language=&multisite=no&random=pf3oq1y3vx
2. Confirm the "address bar" on the Playground page reflects the actual,
correct URL:
`/wp-admin/admin.php?page=html-api-debugger&html=%3Cdiv%3E%0A1%0A2%0A3%0A%3C%2Fdiv%3E`
3. Confirm you can see the following HTML
```
<div>
1
2
3
</div>
```
cc @sirreal @bgrgicak
| */ | ||
| // Get the content window while e.currentTarget is available. | ||
| // It will be undefined on the next event loop tick. | ||
| const contentWindow = e.currentTarget!.contentWindow; |
There was a problem hiding this comment.
Could this be related to the async event handler?
I've done some testing (not on playground) and with an async event handler the behavior seemed less reliable. However, with the sync event handler, e.target.contentWindow.location.href seemed to reliably be the expected value.
I don't know whether target/currentTarget matters, I suspect not, but target seemed to work well in my testing the load event on the iframe.
There was a problem hiding this comment.
Yeah, the information is lost after the await. I was thinking it's related to React and how it clears currentTarget after the synchronous event handler returns, but now that I think about it, React shouldn't be in the mix here. You may be right about the target/currentTarget – was the latter affected by bubbling?
| // Get the content window while e.currentTarget is available. | ||
| // It will be undefined on the next event loop tick. | ||
| const contentWindow = e.currentTarget!.contentWindow; | ||
| await new Promise((resolve) => setTimeout(resolve, 0)); |
There was a problem hiding this comment.
This doesn't work in Safari and Firefox.
Locally in Safari, it started working when I increased the timeout to 10, but that doesn't mean the exact timeout will always work.
There was a problem hiding this comment.
Good spot! I wonder what's the root cause of this behavior. A setInterval and polling twice per second would likely solve this, but I'm hesitant of just throwing it in without fully understanding the problem.
|
Oh wow, synchronizing navigables histories is an entire thing: https://html.spec.whatwg.org/dev/browsing-the-web.html#centralized-modifications-of-session-history |
|
What that boils down to is:
|
| // We need to use the html-api-debugger plugin to test this because | ||
| // most wp-admin pages enforce a redirect to a sanitized (broken) | ||
| // version of the URL. |
There was a problem hiding this comment.
Is this because of the login redirect Playground does, or is it a WordPress redirect that sanitizes the URL?
| home_url($redirect_url), | ||
| 302 | ||
| ); | ||
| $redirect_url = home_url($redirect_url); |
There was a problem hiding this comment.
@adamziel we don't need to force this to a absolute URL anymore because we have a a fix for the relative URL redirects in Safari.
| $redirect_url = home_url($redirect_url); |
There was a problem hiding this comment.
I hope that you don't mind, that I merged trunk into your PR and resolved the conflict with the Safari redirect fix.
|
Thanks for rebasing @bgrgicak! The test link is failing indeed, not good!
I'm confused by the "because of the HTML in the URL" part. What do you mean? How is that causing a failure? |
|
Bumping |
Ignore that part, when I tested the blueprint, removing the Later I also realized it was related to the WP versions, but it was late and I wanted to do more research in the morning before commenting anything. I ran the Webkit test locally a couple of times and it passes locally. |
Its minimum version was changed to latest (6.7) and does rely on new functionality. Sorry it broke the test! |
|
I've disabled that e2e test also in Safari. Let's get the fix in and keep monitoring the problem in Firefox and Safari. It's such a weird issue with close to no reading material out there and I can't think of any other solution anyway. |
This PR:
wp_redirect()call withheader("Location: ")to ensure support for all valid redirection URLs.iframeURL when theloadevent handler runs.Ditching
wp_redirect()The
wp_redirect()call was introduced in #1856 to handle the post-autologin redirect. Unfortunately, it strips valid sequences such as%0Aand%0Dfrom the redirection URL. This isn't useful in Playground and breaks valid use-cases such as using the?url=parameter to initializehtml-api-debuggerwith a valid HTML markup containing newlines.Timeout before probing
contentWindow.location.hrefWhen navigating to a page with %0A sequences (encoded newlines) in the query string, the
location.hrefproperty of the iframe's content window doesn't seem to reflect them. Everything else is in place, but not the %0A sequences.Weirdly, these sequences are available after the next event loop tick – hence the
setTimeout(0).The exact cause is unclear to me. The WHATWG HTML Standard [1] has a few hints:
But there doesn't seem to be any concrete explanation and no recommended remediation. If anyone has a clue, please share it in a GitHub issue or start a new PR.
[1] https://html.spec.whatwg.org/multipage/document-sequences.html#nav-active-history-entry
Testing instructions
CI tests aside, try this:
/wp-admin/admin.php?page=html-api-debugger&html=%3Cdiv%3E%0A1%0A2%0A3%0A%3C%2Fdiv%3Ecc @sirreal @bgrgicak