-
Notifications
You must be signed in to change notification settings - Fork 270
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
Network access in the browser #85
Comments
For posterity: I tried a custom Request_Transport that tunneled all traffic through browser's Interestingly, I remember that WordPress Plugin Directory did not work in this setup. However, @dd32 pointed out that it exposes the correct access-control headers:
So perhaps there is a way to support at least the |
Networking is supported in the Node.js build as of #119 – PHP sends data through a I can think of three ways to implement in-browser support:
|
Also linking to this related discussion. |
Libraries like Composer require HTTPS and they verify the peer certificate by default: https://github.com/composer/composer/blob/11879ea737978fabb8127616e703e571ff71b184/src/Composer/Util/StreamContextFactory.php#L183-L197 As a workaround, networking in the browser could:
This will only work for endpoints exposing proper CORS headers, but it's a start. |
why not use a real chain of trust? particularly if we're trying to make it easy to instantly spool up systems with a blueprint, this could so easily lead to cross-site attacks: "Hey look at the plugin I wrote: [malware link]" for what it's worth, the default Erlang net library sets maybe I'm misreading this, but I'd rather us avoid that mistake if it's what I think we're talking about |
We do in Node.js. Browsers can’t open raw TCP sockets so we need to re-issue the request using fetch(). The only way to do it is to MITM the PHP program to parse the encrypted request data. |
Hosting a websocket proxy on e.g. free CloudFlare tier could solve this for now. |
Possible candidates:
EDIT: Oh, I see there's already something like this implemented in |
Yup, it is used in the |
I wonder what could be achieved, if so, by using the Cloudflare TCP Sockets and running WP Playground on Cloudflare Worker / WASM / NodeJS? |
#1051 implements a HTTPS termination function. All PHP-initiated network traffic is intercepted by a "fake WebSocket" instance which then offers a self-signed HTTPS certificate and reads the raw HTTP traffic, rewrites it as a That PR needs a lot of cleaning up, but the concept seems to be solid. It would unblock support for |
It took 1,5 years but we now have a clear path to resolving this issue 🎉
This would enable requesting all CORS-enabled HTTPS endpoints. For full networking support, we'd also need the following:
The proxy wouldn't be hosted on Playground.wordpress.net as it would be a resource drain, but we could make spinning your own proxy instance easy enough. Nice to haves:
|
Ships the Node.js version of PHP built with `--with-libcurl` option to support the curl extension. It also changes two nuances in the overall PHP build process: * It replaces the `select(2)` function using `-Wl,--wrap=select` emcc option instead of patching PHP source code – this enables supporting asynchronous `select(2)` in curl without additional patches. * Brings the `__wrap_select` implementation more in line with `select(2)`, add support for `POLLERR`. * Adds support for polling file descriptors that represent neither child processes nor streams in `poll(2)` – that's because `libcurl` polls `/dev/urandom`. Builds on top of and supersedes #1133 ## Debugging Asyncify problems The [typical way of resolving Asyncify crashes](https://wordpress.github.io/wordpress-playground/architecture/wasm-asyncify/) didn't work during the work on this PR. Functions didn't come up in the error messages and even raw stack traces. The reasons are unclear. [The JSPI build of PHP](#1339) was more helpful as it enabled logging the current stack trace in all the asynchronous calls, which quickly revealed all the missing `ASYNCIFY_ONLY` functions. This is the way to debug any future issues until we fully migrate to JSPI. ## Testing Instructions Confirm the CI checks pass. This PR ships a few new tests specifically targeting networking with curl. ## Related resources * #85 * #1093 --------- Co-authored-by: Adam Zieliński <adam@adamziel.com> Co-authored-by: MHO <yannick@chillpills.io>
## What is this PR doing? Due to the Content Security Policy, the link to the GitHub issue does not open within the Playground 'Add new plugin' and 'Add new theme' pages. To fix this, add the _target_ attribute to load the link in a new tab. ## What problem is it solving? The error occurs when someone clicks on the "experimental, opt-in feature" link within the Playground due to the CSP. ## How is the problem addressed? Added the **target** attribute to the hyperlink to load the link in a new tab. ## Testing Instructions 1. Open playground 2. Navigate to the **Plugins > Add New Plugins** or **Appearance > Themes > Add New Theme (button)** 3. You can notice the admin error notice mentioning "Network access is an [experimental, opt-in feature](#85), which means you need to enable it to allow Playground to access the Plugins/Themes directories." 4. Click on the "experimental, opt-in feature" hyperlink, where you can notice the GitHub issue link is not loaded due to the CSP.
@adamziel would love to chat about this at WCUS Contributor Day if you'll be around? |
Enables the CURL PHP extension on playground.wordpress.net when networking is enabled. The heavy lifting was done in #1926. All this PR does is: * Enables the curl extension * Rebuilds PHP.wasm for the web * Enables curl_exec and curl_multiexec functions in web browsers * Unrelated – adds a JSPI vs Asyncify indication to the SAPI name so that we can easily learn which PHP.wasm build Playground is running. Related to #85 Closes #1008 ## Testing instrucions Confirm the new E2E tests are sound and that they work in CI. You could also try installing a CURL-reliant plugin such as Plausible and confirm it installs without the fatal errors reported in #1008
I merged this significant milestone earlier today: Next up: |
Enables the CURL PHP extension on [playground.wordpress.net](http://playground.wordpress.net/) when networking is enabled. This is made possible by the TLS 1.2 implementation merged in #1926. This PR: * Enables the curl extension * Rebuilds PHP.wasm for the web * Enables curl_exec and curl_multiexec functions in web browsers * **Strips the response content-length and switches to Transfer-Encoding: Chunked** * Unrelated – adds a JSPI vs Asyncify indication to the SAPI name so that we can easily learn which PHP.wasm build Playground is running Related to #85 Closes #1008 ## Why use Transfer-Encoding: chunked? Web servers often respond with a combination of Content-Length and Content-Encoding. For example, a 16kb text file may be compressed to 4kb with gzip and served with a Content-Encoding of `gzip` and a Content-Length of 4KB. The web browser, however, exposes neither the Content-Encoding header nor the gzipped data stream. All we have access to is the original Content-Length value of the gzipped file and a decompressed data stream. If we just pass that along to the PHP-side request handler, it would see a 16KB body stream with a Content-Length of 4KB. It would then truncate the body stream at 4KB and discard the rest of the data. This is not what we want. To correct that behavior, we're stripping the Content-Length entirely. We do that for every single response because we don't have any way of knowing whether any Content-Encoding was used. Furthermore, we can't just calculate the correct Content-Length value without consuming the entire content stream – and we want to pass each data chunk to PHP as we receive it. Instead of a fixed Content-Length, this PR uses Content-Encoding: Chunked, and then provides a per-chunk Content-Length. ## Testing instrucions Confirm the new E2E tests are sound and that they work in CI. You could also try installing a CURL-reliant plugin such as Plausible and confirm it installs without the fatal errors reported in #1008
Curl is available in web browsers since #1935. To solve, say, ~80% of the problem, we'd need to open up the CORS Proxy beyond talking to git. This is coming in the short to medium term. To solve 100% of the problem, we'd need to tunnel the raw TCP traffic coming from Playground over a persistent WebSocket connection. In this scenario, we'd need a For now, here's what we need to close this issue: |
Latest status
Curl and tcp over fetch() are now a part of WordPress Playground 🎉 Here's what we still need to close this issue:
Description
WordPress Playground only has a partial support for network calls.
Types of network calls in WordPress
wp_safe_remote_get
As of #724, Playground is capable of translating
wp_safe_remote_get
calls into JavaScriptfetch()
requests. This has limitations:Arbitrary network calls
Other methods of accessing the network, such as
libcurl
orfile_get_contents
, are not supported yet.Web browsers do not allow the WebAssembly code to access the internet directly yet. A native socket API may or may not be released in the future, but there isn't one for now. #1093 would improve the situation.
In Node.js, Playground access the network using the following method:
fetch()
orWebSocket
This may not be viable on the web as someone would have to pay for the hardware to run the proxy on, and the proxy's nature mean there are security risks related to accessing the local network.
Solution
After 1,5 years of exploring and discussing, this issue finally has a path forward:
file_get_contents
,curl_exec
etc. and without going throughwp_safe_remote_get()
.For full networking support, we'd also need the following:
Nice to haves:
Limitations of the approach
Limitations without the network proxy:
All of the above could be resolved by plugging in a network proxy.
Other Alternatives
The text was updated successfully, but these errors were encountered: