Skip to content
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

[Exploration] Add Soap PHP library support #1986

Draft
wants to merge 8 commits into
base: trunk
Choose a base branch
from

Conversation

bgrgicak
Copy link
Collaborator

@bgrgicak bgrgicak commented Nov 5, 2024

This PR is an experiment and it's not intended to be merged.

This PR adds Soap support to PHP, by building PHP with --enable-soap.

Progress on adding Soap support

I was able to build PHP 8.0 with Soap and can see it's enabled in PHP Info.

To recompile PHP you can use npm run recompile:php:web:asyncify:8.0 for a single version, or all versions using npm run recompile:php.
See full list of recompile commands here.

TODO: Check if Soap works in Playground

We need to check if Soap works in Playground.

I tried a test script from Stack overflow but it failed with this error

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://www.w3schools.com/xml/tempconvert.asmx?WSDL' : failed to load external entity "https://www.w3schools.com/xml/tempconvert.asmx?WSDL" in /wordpress/soap-test.php:3 Stack trace: #0 /wordpress/soap-test.php(3): SoapClient->__construct('https://www.w3s...') #1 {main} thrown in /wordpress/soap-test.php on line 3

Fixes #1236

Testing Instructions (or ideally a Blueprint)

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Nov 5, 2024

@vyskoczilova would you be interested in taking a look at Soap and see where it fails?

To test the Node version, you could add tests to packages/php-wasm/node/src/test/php.spec.ts.

For the Web version, you could write a PHP file during the Website boot here.

For example:

	await php.writeFile(
		'/wordpress/soap-test.php',
		`<?php
		//Create the client object
		$client = new SoapClient('https://gist.githubusercontent.com/bgrgicak/f8554eb8ee4a1adf1587e3badda60638/raw/7c1416f374e1be6a63835d7cac319d92a5397625/soap-test-data.asmx');
		echo json_encode($client->CelsiusToFahrenheit(array('Celsius' => 100)));
		?>`
	);

And call it using this URL http://127.0.0.1:5400/website-server/?php=8.0&url=%2Fsoap-test.php&networking=yes

@bgrgicak bgrgicak marked this pull request as draft November 5, 2024 16:45
@bgrgicak bgrgicak changed the title [PHP library] Add Soap support [Exploration] Add Soap PHP library support Nov 5, 2024
@adamziel
Copy link
Collaborator

adamziel commented Nov 5, 2024

I tried a test script from Stack overflow but it failed with this error

Was networking enabled?

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Nov 5, 2024

I tried a test script from Stack overflow but it failed with this error

Was networking enabled?

With networking, it's a WASM error. We need to add a test to php-asyncify.spec.ts and see what functions are missing.

[05-Nov-2024 21:27:23 UTC] WASM Crash Fatal: 
"unreachable" WASM instruction executed.

The typical reason is a PHP function missing from the ASYNCIFY_ONLY
list when building PHP.wasm.

You will need to file a new issue in the WordPress Playground repository
and paste this error message there:

https://github.com/WordPress/wordpress-playground/issues/new

If you're a core developer, the typical fix is to:

* Isolate a minimal reproduction of the error
* Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
* Run 'npm run fix-asyncify'
* Commit the changes, push to the repo, release updated NPM packages

Below is a list of all the PHP functions found in the stack trace to
help with the minimal reproduction. If they're all already listed in
the Dockerfile, you'll need to trigger this error again with long stack
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
CLI option: 

    * <unknown>
 Error: 
"unreachable" WASM instruction executed.

The typical reason is a PHP function missing from the ASYNCIFY_ONLY
list when building PHP.wasm.

You will need to file a new issue in the WordPress Playground repository
and paste this error message there:

https://github.com/WordPress/wordpress-playground/issues/new

If you're a core developer, the typical fix is to:

* Isolate a minimal reproduction of the error
* Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
* Run 'npm run fix-asyncify'
* Commit the changes, push to the repo, release updated NPM packages

Below is a list of all the PHP functions found in the stack trace to
help with the minimal reproduction. If they're all already listed in
the Dockerfile, you'll need to trigger this error again with long stack
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
CLI option: 

    * <unknown>

    at #handleRequest (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php.ts?t=1730712623681:658:24)
    at async PHP.run (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php.ts?t=1730712623681:369:24)
    at async #dispatchToPHP (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-request-handler.ts?t=1730836217733:303:24)
    at async #spawnPHPAndDispatchRequest (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-request-handler.ts?t=1730836217733:272:14)
    at async PlaygroundWorkerEndpoint.request (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-worker.ts?t=1730452410128:65:12)

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Nov 6, 2024

I ran npm run fix-asyncify and got some new Asyncify functions.

The unit test seems to pass, but in the browser, it fails with another WASM error.

[06-Nov-2024 08:15:01 UTC] WASM Crash Fatal: 
"unreachable" WASM instruction executed.

The typical reason is a PHP function missing from the ASYNCIFY_ONLY
list when building PHP.wasm.

You will need to file a new issue in the WordPress Playground repository
and paste this error message there:

https://github.com/WordPress/wordpress-playground/issues/new

If you're a core developer, the typical fix is to:

* Isolate a minimal reproduction of the error
* Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
* Run 'npm run fix-asyncify'
* Commit the changes, push to the repo, release updated NPM packages

Below is a list of all the PHP functions found in the stack trace to
help with the minimal reproduction. If they're all already listed in
the Dockerfile, you'll need to trigger this error again with long stack
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
CLI option: 

    * <unknown>
 Error: 
"unreachable" WASM instruction executed.

The typical reason is a PHP function missing from the ASYNCIFY_ONLY
list when building PHP.wasm.

You will need to file a new issue in the WordPress Playground repository
and paste this error message there:

https://github.com/WordPress/wordpress-playground/issues/new

If you're a core developer, the typical fix is to:

* Isolate a minimal reproduction of the error
* Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
* Run 'npm run fix-asyncify'
* Commit the changes, push to the repo, release updated NPM packages

Below is a list of all the PHP functions found in the stack trace to
help with the minimal reproduction. If they're all already listed in
the Dockerfile, you'll need to trigger this error again with long stack
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
CLI option: 

    * <unknown>

    at #handleRequest (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php.ts:658:24)
    at async PHP.run (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php.ts:369:24)
    at async #dispatchToPHP (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-request-handler.ts:303:24)
    at async #spawnPHPAndDispatchRequest (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-request-handler.ts:272:14)
    at async PlaygroundWorkerEndpoint.request (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-worker.ts:65:12)

@adamziel
Copy link
Collaborator

adamziel commented Nov 6, 2024

@bgrgicak It would probably work with JSPI. Finding the right place to call console.trace() with a JSPI build would be the easiest way to get a list of the functions involved.

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Nov 7, 2024

I spent a bit more time testing this.

First I worked on a minimal SOAP example. It works well in the terminal, but it times out with an error in the browser. I don't have experience with SoapClients and assume that I'm doing something wrong.

Here are my testing results so far.

Node

I added a SoapServer for the test to avoid remote requests and also to test the server.

The unit test doesn't return any errors, but there is a PHP error Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:3000/soap-server.php' : failed to load external entity &quot;http://localhost:3000/soap-server.php.
This is caused by missing network support in test where it runs in the Node environment.
I'm not sure why the Node environment wouldn't support network requests, so that's a possible next step to research.

Web

When I test it in the browser by adding this code to the Website boot here.

	php.writeFile(
		'/wordpress/soap-server.php',
		`<?php
		class TestSoapServer
		{
			public function getMessage()
			{
				return 'Hello, World!';
			}
		}
		try {
			$options = [
				'uri' => ${phpVar(options.siteUrl)},
			];
			$server = new SoapServer(null, $options);
			$server->setClass('TestSoapServer');
			$server->handle();
		} catch (SoapFault $e) {
			echo "Server Error: " . $e->getMessage();
		}`
	);

	php.writeFile(
		'/wordpress/soap-client.php',
		`<?php
		$client = new SoapClient('${options.siteUrl}/soap-server.php');
		echo json_encode($client->getMessage());
		`
	);

Asyncify

It results in another Asyncify error.

[07-Nov-2024 09:44:41 UTC] JavaScript Debug: Number of open Playground tabs is: 2
[07-Nov-2024 09:44:45 UTC] WASM Crash Fatal: 
"unreachable" WASM instruction executed.

The typical reason is a PHP function missing from the ASYNCIFY_ONLY
list when building PHP.wasm.

You will need to file a new issue in the WordPress Playground repository
and paste this error message there:

https://github.com/WordPress/wordpress-playground/issues/new

If you're a core developer, the typical fix is to:

* Isolate a minimal reproduction of the error
* Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
* Run 'npm run fix-asyncify'
* Commit the changes, push to the repo, release updated NPM packages

Below is a list of all the PHP functions found in the stack trace to
help with the minimal reproduction. If they're all already listed in
the Dockerfile, you'll need to trigger this error again with long stack
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
CLI option: 

    * <unknown>
 Error: 
"unreachable" WASM instruction executed.

The typical reason is a PHP function missing from the ASYNCIFY_ONLY
list when building PHP.wasm.

You will need to file a new issue in the WordPress Playground repository
and paste this error message there:

https://github.com/WordPress/wordpress-playground/issues/new

If you're a core developer, the typical fix is to:

* Isolate a minimal reproduction of the error
* Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
* Run 'npm run fix-asyncify'
* Commit the changes, push to the repo, release updated NPM packages

Below is a list of all the PHP functions found in the stack trace to
help with the minimal reproduction. If they're all already listed in
the Dockerfile, you'll need to trigger this error again with long stack
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
CLI option: 

    * <unknown>

    at #handleRequest (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php.ts:658:24)
    at async PHP.run (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php.ts:369:24)
    at async #dispatchToPHP (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-request-handler.ts?t=1730970591007:303:24)
    at async #spawnPHPAndDispatchRequest (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-request-handler.ts?t=1730970591007:272:14)
    at async PlaygroundWorkerEndpoint.request (http://127.0.0.1:5400/@fs/Users/bero/Projects/wordpress-playground/packages/php-wasm/universal/src/lib/php-worker.ts:65:12)

JSPI

JSPI returns a different error from Node.

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://127.0.0.1:5400/scope:honest-cozy-ocean/soap-server.php' : Document is empty in /wordpress/soap-client.php:2 Stack trace: #0 /wordpress/soap-client.php(2): SoapClient->__construct('http://127.0.0....') #1 {main} thrown in /wordpress/soap-client.php on line 2

@adamziel
Copy link
Collaborator

adamziel commented Nov 13, 2024

Asyncify is tedious. It's much easier to get it to work with JSPI first and figure out Asyncify from there.

The JSPI error message tells me it's receiving an empty response instead of the expected XML document from the requested URL. Is that so? What happens when that URL is requested with CURL? Does it respond with the correct XML document? Or is it an empty response or error 500? SOAP needs to be explicitly enabled on the target site, perhaps it isn't?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PHP SoapClient extension
2 participants