diff --git a/README.md b/README.md
index 11e1e38..f9b6b19 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,29 @@
-# Aiwass
+# RPCii (ć—§Aiwass)
-Aiwass is an RPC client and server library.
+RPCii is an RPC client and server library.
An Index compatible route handler is provided to make it really low effort to get a server going.
## Requirements and Dependencies
-Aiwass currently targets **PHP 8.3** with the `msgpack` extension installed.
+RPCii currently targets **PHP 8.3** with the `msgpack` extension installed.
## Versioning
-Aiwass versioning will follows the [Semantic Versioning specification v2.0.0](https://semver.org/spec/v2.0.0.html).
+RPCii versioning will follows the [Semantic Versioning specification v2.0.0](https://semver.org/spec/v2.0.0.html).
-Changes to minimum required PHP version other major overhauls to Aiwass itself that break compatibility will be reasons for incrementing the major version.
+Changes to minimum required PHP version other major overhauls to RPCii itself that break compatibility will be reasons for incrementing the major version.
-Aiwass depends on Index, but its versioning depends on the minimum PHP version and should thus be fairly inconsequential.
+RPCii depends on Index, but its versioning depends on the minimum PHP version and should thus be fairly inconsequential.
Previous major versions may be supported for a time with backports depending on what projects of mine still target older versions of PHP.
-The version is stored in the root of the repository in a file called `VERSION` and can be read out within Aiwass using `Aiwass\Aiwass::version()`.
+The version is stored in the root of the repository in a file called `VERSION` and can be read out within RPCii using `RPCii\RPCii::version()`.
## Contribution
-By submitting code for inclusion in the main Aiwass source tree you agree to transfer ownership of the code to the project owner.
+By submitting code for inclusion in the main RPCii source tree you agree to transfer ownership of the code to the project owner.
The contributor will still be attributed for the contributed code, unless they ask for this attribution to be removed.
This is to avoid intellectual property rights traps and drama that could lead to blackmail situations.
If you do not agree with these terms, you are free to fork off.
@@ -31,4 +31,4 @@ If you do not agree with these terms, you are free to fork off.
## Licencing
-Aiwass is available under the BSD 3-Clause Clear License, a full version of which is enclosed in the LICENCE file.
+RPCii is available under the BSD 3-Clause Clear License, a full version of which is enclosed in the LICENCE file.
diff --git a/VERSION b/VERSION
index 9084fa2..227cea2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.0
+2.0.0
diff --git a/composer.json b/composer.json
index 15dde6f..73b4c9a 100644
--- a/composer.json
+++ b/composer.json
@@ -1,8 +1,8 @@
{
- "name": "flashwave/aiwass",
- "description": "Shared HTTP RPC client/server library.",
+ "name": "flashii/rpcii",
+ "description": "HTTP RPC client/server library.",
"type": "library",
- "homepage": "https://railgun.sh/aiwass",
+ "homepage": "https://railgun.sh/rpcii",
"license": "bsd-3-clause-clear",
"require": {
"php": ">=8.3",
@@ -10,8 +10,8 @@
"flashwave/index": "^0.2410"
},
"require-dev": {
- "phpunit/phpunit": "^11.2",
- "phpstan/phpstan": "^1.11"
+ "phpunit/phpunit": "^11.4",
+ "phpstan/phpstan": "^2.0"
},
"authors": [
{
@@ -23,7 +23,7 @@
],
"autoload": {
"psr-4": {
- "Aiwass\\": "src"
+ "RPCii\\": "src"
}
}
}
diff --git a/composer.lock b/composer.lock
index a32f3f5..11f9b07 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,15 +4,15 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "8d01741caad2805272e619b4aa3c3c5e",
+ "content-hash": "f82764057cc610971b1823a40f95da29",
"packages": [
{
"name": "flashwave/index",
- "version": "v0.2410.42339",
+ "version": "v0.2410.191603",
"source": {
"type": "git",
"url": "https://patchii.net/flash/index.git",
- "reference": "d3e4d0985a1189d15fb8ed9eb105830c9dc38c4d"
+ "reference": "17cdb4d1c239241200d7e30968122a8cd8b26509"
},
"require": {
"ext-mbstring": "*",
@@ -33,6 +33,14 @@
},
"type": "library",
"autoload": {
+ "files": [
+ "src/Cache/ArrayCache/_ndx.php",
+ "src/Cache/Memcached/_ndx.php",
+ "src/Cache/Valkey/_ndx.php",
+ "src/Db/MariaDb/_ndx.php",
+ "src/Db/NullDb/_ndx.php",
+ "src/Db/Sqlite/_ndx.php"
+ ],
"psr-4": {
"Index\\": "src"
}
@@ -51,7 +59,7 @@
],
"description": "Composer package for the common library for my projects.",
"homepage": "https://railgun.sh/index",
- "time": "2024-10-04T23:39:32+00:00"
+ "time": "2024-10-19T16:04:17+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -122,16 +130,16 @@
},
{
"name": "symfony/mime",
- "version": "v7.1.5",
+ "version": "v7.1.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff"
+ "reference": "caa1e521edb2650b8470918dfe51708c237f0598"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/711d2e167e8ce65b05aea6b258c449671cdd38ff",
- "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598",
+ "reference": "caa1e521edb2650b8470918dfe51708c237f0598",
"shasum": ""
},
"require": {
@@ -186,7 +194,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v7.1.5"
+ "source": "https://github.com/symfony/mime/tree/v7.1.6"
},
"funding": [
{
@@ -202,7 +210,7 @@
"type": "tidelift"
}
],
- "time": "2024-09-20T08:28:38+00:00"
+ "time": "2024-10-25T15:11:02+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -673,16 +681,16 @@
},
{
"name": "twig/twig",
- "version": "v3.14.0",
+ "version": "v3.14.2",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72"
+ "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
- "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a",
+ "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a",
"shasum": ""
},
"require": {
@@ -736,7 +744,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
- "source": "https://github.com/twigphp/Twig/tree/v3.14.0"
+ "source": "https://github.com/twigphp/Twig/tree/v3.14.2"
},
"funding": [
{
@@ -748,22 +756,22 @@
"type": "tidelift"
}
],
- "time": "2024-09-09T17:55:12+00:00"
+ "time": "2024-11-07T12:36:22+00:00"
}
],
"packages-dev": [
{
"name": "myclabs/deep-copy",
- "version": "1.12.0",
+ "version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c"
+ "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
- "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
+ "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
"shasum": ""
},
"require": {
@@ -802,7 +810,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
},
"funding": [
{
@@ -810,20 +818,20 @@
"type": "tidelift"
}
],
- "time": "2024-06-12T14:39:25+00:00"
+ "time": "2024-11-08T17:47:46+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.3.0",
+ "version": "v5.3.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a"
+ "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3abf7425cd284141dc5d8d14a9ee444de3345d1a",
- "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b",
+ "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b",
"shasum": ""
},
"require": {
@@ -866,9 +874,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1"
},
- "time": "2024-09-29T13:56:26+00:00"
+ "time": "2024-10-08T18:51:32+00:00"
},
{
"name": "phar-io/manifest",
@@ -990,20 +998,20 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.12.5",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "7e6c6cb7cecb0a6254009a1a8a7d54ec99812b17"
+ "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/7e6c6cb7cecb0a6254009a1a8a7d54ec99812b17",
- "reference": "7e6c6cb7cecb0a6254009a1a8a7d54ec99812b17",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d",
+ "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d",
"shasum": ""
},
"require": {
- "php": "^7.2|^8.0"
+ "php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
@@ -1044,39 +1052,39 @@
"type": "github"
}
],
- "time": "2024-09-26T12:45:22+00:00"
+ "time": "2024-11-11T15:43:04+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "11.0.6",
+ "version": "11.0.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45"
+ "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ebdffc9e09585dafa71b9bffcdb0a229d4704c45",
- "reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca",
+ "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^5.1.0",
+ "nikic/php-parser": "^5.3.1",
"php": ">=8.2",
- "phpunit/php-file-iterator": "^5.0.1",
+ "phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-text-template": "^4.0.1",
"sebastian/code-unit-reverse-lookup": "^4.0.1",
"sebastian/complexity": "^4.0.1",
"sebastian/environment": "^7.2.0",
"sebastian/lines-of-code": "^3.0.1",
- "sebastian/version": "^5.0.1",
+ "sebastian/version": "^5.0.2",
"theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "phpunit/phpunit": "^11.0"
+ "phpunit/phpunit": "^11.4.1"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -1114,7 +1122,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.6"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7"
},
"funding": [
{
@@ -1122,7 +1130,7 @@
"type": "github"
}
],
- "time": "2024-08-22T04:37:56+00:00"
+ "time": "2024-10-09T06:21:38+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1371,16 +1379,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.3.6",
+ "version": "11.4.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "d62c45a19c665bb872c2a47023a0baf41a98bb2b"
+ "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d62c45a19c665bb872c2a47023a0baf41a98bb2b",
- "reference": "d62c45a19c665bb872c2a47023a0baf41a98bb2b",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76",
+ "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76",
"shasum": ""
},
"require": {
@@ -1394,21 +1402,21 @@
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
- "phpunit/php-code-coverage": "^11.0.6",
+ "phpunit/php-code-coverage": "^11.0.7",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-invoker": "^5.0.1",
"phpunit/php-text-template": "^4.0.1",
"phpunit/php-timer": "^7.0.1",
"sebastian/cli-parser": "^3.0.2",
"sebastian/code-unit": "^3.0.1",
- "sebastian/comparator": "^6.1.0",
+ "sebastian/comparator": "^6.1.1",
"sebastian/diff": "^6.0.2",
"sebastian/environment": "^7.2.0",
"sebastian/exporter": "^6.1.3",
"sebastian/global-state": "^7.0.2",
"sebastian/object-enumerator": "^6.0.1",
"sebastian/type": "^5.1.0",
- "sebastian/version": "^5.0.1"
+ "sebastian/version": "^5.0.2"
},
"suggest": {
"ext-soap": "To be able to generate mocks based on WSDL files"
@@ -1419,7 +1427,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "11.3-dev"
+ "dev-main": "11.4-dev"
}
},
"autoload": {
@@ -1451,7 +1459,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.6"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3"
},
"funding": [
{
@@ -1467,7 +1475,7 @@
"type": "tidelift"
}
],
- "time": "2024-09-19T10:54:28+00:00"
+ "time": "2024-10-28T13:07:50+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -1641,16 +1649,16 @@
},
{
"name": "sebastian/comparator",
- "version": "6.1.0",
+ "version": "6.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d"
+ "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa37b9e2ca618cb051d71b60120952ee8ca8b03d",
- "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739",
+ "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739",
"shasum": ""
},
"require": {
@@ -1661,12 +1669,12 @@
"sebastian/exporter": "^6.0"
},
"require-dev": {
- "phpunit/phpunit": "^11.3"
+ "phpunit/phpunit": "^11.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "6.1-dev"
+ "dev-main": "6.2-dev"
}
},
"autoload": {
@@ -1706,7 +1714,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
- "source": "https://github.com/sebastianbergmann/comparator/tree/6.1.0"
+ "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1"
},
"funding": [
{
@@ -1714,7 +1722,7 @@
"type": "github"
}
],
- "time": "2024-09-11T15:42:56+00:00"
+ "time": "2024-10-31T05:30:08+00:00"
},
{
"name": "sebastian/complexity",
@@ -2340,16 +2348,16 @@
},
{
"name": "sebastian/version",
- "version": "5.0.1",
+ "version": "5.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
- "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4"
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4",
- "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874",
"shasum": ""
},
"require": {
@@ -2382,7 +2390,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
"security": "https://github.com/sebastianbergmann/version/security/policy",
- "source": "https://github.com/sebastianbergmann/version/tree/5.0.1"
+ "source": "https://github.com/sebastianbergmann/version/tree/5.0.2"
},
"funding": [
{
@@ -2390,7 +2398,7 @@
"type": "github"
}
],
- "time": "2024-07-03T05:13:08+00:00"
+ "time": "2024-10-09T05:16:32+00:00"
},
{
"name": "theseer/tokenizer",
diff --git a/phpdoc.xml b/phpdoc.xml
index c06412c..6b86daa 100644
--- a/phpdoc.xml
+++ b/phpdoc.xml
@@ -3,17 +3,17 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://www.phpdoc.org"
xsi:noNamespaceSchemaLocation="data/xsd/phpdoc.xsd">
-
Aiwass Documentation
+ RPCii Documentation
-
+
latest
public
- Aiwass
+ RPCii
diff --git a/phpstan.neon b/phpstan.neon
index 39c5d92..f334b99 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -3,5 +3,7 @@ parameters:
checkUninitializedProperties: true
checkImplicitMixed: true
checkBenevolentUnionTypes: true
+ treatPhpDocTypesAsCertain: false
paths:
- src
+ - tests
diff --git a/phpunit.xml b/phpunit.xml
index 0dd4194..c09051b 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -1,6 +1,6 @@
2,
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_TIMEOUT => 5,
- CURLOPT_USERAGENT => 'Aiwass',
+ CURLOPT_USERAGENT => 'RPCii',
]);
}
public function __destruct() {
- $this->close();
- }
-
- public function close(): void {
curl_close($this->handle);
}
@@ -87,7 +83,6 @@ class CurlHttpRequest implements IHttpRequest {
if($response === false)
throw new RuntimeException(curl_error($this->handle));
- $this->close();
if($response === true)
return '';
diff --git a/src/Client/IHttpRequest.php b/src/Client/HttpRequest.php
similarity index 88%
rename from src/Client/IHttpRequest.php
rename to src/Client/HttpRequest.php
index 1b516fa..f807c54 100644
--- a/src/Client/IHttpRequest.php
+++ b/src/Client/HttpRequest.php
@@ -1,17 +1,16 @@
$params */
+ private function callProcedure(bool $isAction, string $action, array $params): mixed {
+ $params = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
+
+ $request = ($this->createRequest)();
+ $request->setPost($isAction);
+ $request->setUrl(sprintf('%s/_rpcii/%s', $this->url, $action));
+ $request->setHeader('X-RPCii-Verify', $this->verify->sign($isAction, $action, $params));
+ $request->setParams($params);
+
+ return RpciiMsgPack::decode($request->execute());
+ }
+
+ public function query(string $action, array $params): mixed {
+ return $this->callProcedure(false, $action, $params);
+ }
+
+ public function action(string $action, array $params): mixed {
+ return $this->callProcedure(true, $action, $params);
+ }
+
+ /**
+ * Creates an RPC client with HMAC verification and a suitable HTTP request implementation.
+ *
+ * @param string $url Base RPC url, up to the /_rpcii part.
+ * @param callable(): string $getSecretKey A method that returns the secret key to use.
+ * @return HttpRpcClient An HTTP RPC client!
+ */
+ public static function createHmac(string $url, $getSecretKey): HttpRpcClient {
+ if(extension_loaded('curl'))
+ $createRequest = fn() => new CurlHttpRequest;
+ else
+ $createRequest = fn() => new StreamHttpRequest;
+
+ return new HttpRpcClient(
+ $url,
+ new HmacVerificationProvider($getSecretKey),
+ $createRequest
+ );
+ }
+}
diff --git a/src/Client/IRpcClient.php b/src/Client/IRpcClient.php
deleted file mode 100644
index 7df4018..0000000
--- a/src/Client/IRpcClient.php
+++ /dev/null
@@ -1,37 +0,0 @@
- $params Parameters to query with.
- * @return mixed Result of the query.
- */
- function query(string $action, array $params): mixed;
-
- /**
- * Makes an RPC procedure call.
- *
- * @param string $action Name of the action.
- * @param array $params Parameters to query with.
- * @return mixed Result of the procedure call.
- */
- function procedure(string $action, array $params): mixed;
-}
diff --git a/src/Client/RpcClient.php b/src/Client/RpcClient.php
index 554e2bb..8875453 100644
--- a/src/Client/RpcClient.php
+++ b/src/Client/RpcClient.php
@@ -1,68 +1,37 @@
$params */
- private function callAction(bool $isProcedure, string $action, array $params): mixed {
- $params = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
-
- $request = ($this->createRequest)();
- $request->setPost($isProcedure);
- $request->setUrl(sprintf('%s/_aiwass/%s', $this->url, $action));
- $request->setHeader('X-Aiwass-Verify', $this->verify->sign($isProcedure, $action, $params));
- $request->setParams($params);
-
- return AiwassMsgPack::decode($request->execute());
- }
-
- public function query(string $action, array $params): mixed {
- return $this->callAction(false, $action, $params);
- }
-
- public function procedure(string $action, array $params): mixed {
- return $this->callAction(true, $action, $params);
- }
-
- /**
- * Creates an RPC client with HMAC verification and a suitable HTTP request implementation.
+ * Creates a proxy for this RPC client with a specified namespace.
*
- * @param string $url Base RPC url, up to the /_aiwass part.
- * @param callable(): string $getSecretKey A method that returns the secret key to use.
- * @return RpcClient An RPC client!
+ * @param string $prefix Prefix to apply to the scoped RPC client.
+ * @return RpcClient A scoped RPC client instance.
*/
- public static function createHmac(string $url, $getSecretKey): RpcClient {
- return new RpcClient(
- $url,
- new HmacVerificationProvider($getSecretKey),
- fn() => new CurlHttpRequest,
- );
- }
+ function scopeTo(string $prefix): RpcClient;
+
+ /**
+ * Makes an RPC query.
+ *
+ * @param string $procedure Name of the procedure.
+ * @param array $params Parameters to query with.
+ * @return mixed Result of the query.
+ */
+ function query(string $procedure, array $params): mixed;
+
+ /**
+ * Makes an RPC action call.
+ *
+ * @param string $procedure Name of the procedure.
+ * @param array $params Parameters to query with.
+ * @return mixed Result of the procedure call.
+ */
+ function action(string $procedure, array $params): mixed;
}
diff --git a/src/Client/RpcClientScoped.php b/src/Client/RpcClientScoped.php
deleted file mode 100644
index ca3f4a2..0000000
--- a/src/Client/RpcClientScoped.php
+++ /dev/null
@@ -1,32 +0,0 @@
-base->scopeTo($this->prefix . $prefix);
- }
-
- public function query(string $action, array $params): mixed {
- return $this->base->query($this->prefix . $action, $params);
- }
-
- public function procedure(string $action, array $params): mixed {
- return $this->base->procedure($this->prefix . $action, $params);
- }
-}
diff --git a/src/Client/ScopedRpcClient.php b/src/Client/ScopedRpcClient.php
new file mode 100644
index 0000000..3790a79
--- /dev/null
+++ b/src/Client/ScopedRpcClient.php
@@ -0,0 +1,32 @@
+base->scopeTo($this->prefix . $prefix);
+ }
+
+ public function query(string $procedure, array $params): mixed {
+ return $this->base->query($this->prefix . $procedure, $params);
+ }
+
+ public function action(string $procedure, array $params): mixed {
+ return $this->base->action($this->prefix . $procedure, $params);
+ }
+}
diff --git a/src/Client/StreamHttpRequest.php b/src/Client/StreamHttpRequest.php
new file mode 100644
index 0000000..e9cccfa
--- /dev/null
+++ b/src/Client/StreamHttpRequest.php
@@ -0,0 +1,75 @@
+isPost = $state;
+ }
+
+ public function setUrl(string $url): void {
+ $this->url = $url;
+ }
+
+ public function setHeader(string $name, string $value): void {
+ $this->headers[] = sprintf('%s: %s', $name, $value);
+ }
+
+ public function setParams(string $paramString): void {
+ $this->paramString = $paramString;
+ }
+
+ public function execute(): string {
+ $url = $this->url;
+ if($url === null)
+ throw new RuntimeException('no target url specified');
+
+ $ctx = [];
+
+ if($this->isPost) {
+ $ctx['method'] = 'POST';
+ $this->setHeader('Content-Type', 'application/x-www-form-urlencoded');
+ $ctx['content'] = $this->paramString;
+ } else {
+ $ctx['method'] = 'GET';
+ $url .= str_contains($url, '?') ? '&' : '?';
+ $url .= $this->paramString;
+ }
+
+ $ctx['header'] = implode("\r\n", $this->headers);
+
+ $ctx = stream_context_create(['http' => $ctx]);
+ $handle = fopen($url, 'rb', context: $ctx);
+ if($handle === false)
+ throw new RuntimeException('failed to create HTTP request');
+
+ $response = stream_get_contents($handle);
+ if($response === false)
+ throw new RuntimeException('failed to read response body');
+
+ return $response;
+ }
+
+ /**
+ * Creates a new Stream HTTP Request instance.
+ *
+ * @return StreamHttpRequest File HTTP Request.
+ */
+ public static function create(): StreamHttpRequest {
+ return new StreamHttpRequest;
+ }
+}
diff --git a/src/HmacVerificationProvider.php b/src/HmacVerificationProvider.php
index c580ad4..6eea9e9 100644
--- a/src/HmacVerificationProvider.php
+++ b/src/HmacVerificationProvider.php
@@ -1,9 +1,9 @@
signWith($this->algos[0], $isProcedure, $action, $paramString);
+ public function sign(bool $isAction, string $action, string $paramString): string {
+ return $this->signWith($this->algos[0], $isAction, $action, $paramString);
}
- private function signWith(string $algo, bool $isProcedure, string $action, string $paramString): string {
+ private function signWith(string $algo, bool $isAction, string $action, string $paramString): string {
$time = time();
- $hash = $this->createHash($algo, $time, $isProcedure, $action, $paramString);
+ $hash = $this->createHash($algo, $time, $isAction, $action, $paramString);
- return UriBase64::encode(AiwassMsgPack::encode([
+ return UriBase64::encode(RpciiMsgPack::encode([
'a' => $algo,
't' => $time,
'h' => $hash,
@@ -67,14 +67,14 @@ class HmacVerificationProvider implements IVerificationProvider {
private function createHash(
string $algo,
int $timeStamp,
- bool $isProcedure,
+ bool $isAction,
string $action,
string $paramString
): string {
$data = sprintf(
'^<=>%d<=>%s<=>%s<=>%s<=>$',
$timeStamp,
- $isProcedure ? 'p' : 'q',
+ $isAction ? 'a' : 'q',
$action,
$paramString
);
@@ -92,12 +92,12 @@ class HmacVerificationProvider implements IVerificationProvider {
return in_array($algo, $this->algos);
}
- public function verify(string $userToken, bool $isProcedure, string $action, string $paramString): bool {
+ public function verify(string $userToken, bool $isAction, string $action, string $paramString): bool {
$userToken = UriBase64::decode($userToken);
if($userToken === false)
return false;
- $userTokenInfo = AiwassMsgPack::decode($userToken);
+ $userTokenInfo = RpciiMsgPack::decode($userToken);
if(!is_array($userTokenInfo))
return false;
@@ -114,7 +114,7 @@ class HmacVerificationProvider implements IVerificationProvider {
if(!is_string($userHash))
return false;
- $realHash = $this->createHash($userAlgo, $userTime, $isProcedure, $action, $paramString);
+ $realHash = $this->createHash($userAlgo, $userTime, $isAction, $action, $paramString);
return hash_equals($realHash, $userHash);
}
}
diff --git a/src/Aiwass.php b/src/RPCii.php
similarity index 72%
rename from src/Aiwass.php
rename to src/RPCii.php
index 0addb33..bafc03e 100644
--- a/src/Aiwass.php
+++ b/src/RPCii.php
@@ -1,22 +1,22 @@
*/
+ private array $procedures = [];
+
+ /**
+ * Creates an RPC route handler.
+ *
+ * @param VerificationProvider $verification A verification provider.
+ * @return RpcRouteHandler RPC route handler.
+ */
+ public function createRouteHandler(VerificationProvider $verification): RpcRouteHandler {
+ return new RpcRouteHandler($this, $verification);
+ }
+
+ public function scopeTo(string $prefix): RpcServer {
+ return new ScopedRpcServer($this, $prefix);
+ }
+
+ public function registerProcedure(bool $isAction, string $name, $handler): void {
+ if(array_key_exists($name, $this->procedures))
+ throw new RuntimeException('an procedure with that name has already been registered');
+
+ $this->procedures[$name] = new RpcProcedureInfo($isAction, $name, $handler);
+ }
+
+ public function getProcedureInfo(string $name): ?RpcProcedureInfo {
+ return $this->procedures[$name] ?? null;
+ }
+}
diff --git a/src/Server/IRpcActionHandler.php b/src/Server/IRpcActionHandler.php
deleted file mode 100644
index d49fd2c..0000000
--- a/src/Server/IRpcActionHandler.php
+++ /dev/null
@@ -1,18 +0,0 @@
-isProcedure;
- }
-
- /**
- * Returns the action name.
- *
- * @return string
- */
- public function getName(): string {
- return $this->name;
- }
-
- /**
- * Reads attributes from methods in a IRpcActionHandler instance and registers them to a given IRpcServer instance.
- *
- * @param IRpcServer $server RPC server instance.
- * @param IRpcActionHandler $handler Handler instance.
- */
- public static function register(IRpcServer $server, IRpcActionHandler $handler): void {
- $objectInfo = new ReflectionObject($handler);
- $methodInfos = $objectInfo->getMethods();
-
- foreach($methodInfos as $methodInfo) {
- $attrInfos = $methodInfo->getAttributes(RpcAction::class, ReflectionAttribute::IS_INSTANCEOF);
-
- foreach($attrInfos as $attrInfo) {
- $handlerInfo = $attrInfo->newInstance();
- $server->registerAction(
- $handlerInfo->isProcedure(),
- $handlerInfo->getName(),
- $methodInfo->getClosure($methodInfo->isStatic() ? null : $handler)
- );
- }
- }
+ public function __construct(string $name) {
+ parent::__construct(true, $name);
}
}
diff --git a/src/Server/RpcActionHandler.php b/src/Server/RpcActionHandler.php
deleted file mode 100644
index 4238885..0000000
--- a/src/Server/RpcActionHandler.php
+++ /dev/null
@@ -1,14 +0,0 @@
-isAction;
+ }
+
+ /**
+ * Returns the procedure name.
+ *
+ * @return string
+ */
+ public function getName(): string {
+ return $this->name;
+ }
+
+ /**
+ * Reads attributes from methods in a RpcHandler instance and registers them to a given RpcServer instance.
+ *
+ * @param RpcServer $server RPC server instance.
+ * @param RpcHandler $handler Handler instance.
+ */
+ public static function register(RpcServer $server, RpcHandler $handler): void {
+ $objectInfo = new ReflectionObject($handler);
+ $methodInfos = $objectInfo->getMethods();
+
+ foreach($methodInfos as $methodInfo) {
+ $attrInfos = $methodInfo->getAttributes(RpcProcedure::class, ReflectionAttribute::IS_INSTANCEOF);
+
+ foreach($attrInfos as $attrInfo) {
+ $handlerInfo = $attrInfo->newInstance();
+ $server->registerProcedure(
+ $handlerInfo->isAction(),
+ $handlerInfo->getName(),
+ $methodInfo->getClosure($methodInfo->isStatic() ? null : $handler)
+ );
+ }
+ }
}
}
diff --git a/src/Server/RpcActionInfo.php b/src/Server/RpcProcedureInfo.php
similarity index 71%
rename from src/Server/RpcActionInfo.php
rename to src/Server/RpcProcedureInfo.php
index c56eba5..b077d44 100644
--- a/src/Server/RpcActionInfo.php
+++ b/src/Server/RpcProcedureInfo.php
@@ -1,9 +1,9 @@
isProcedure;
+ public function isAction(): bool {
+ return $this->isAction;
}
/**
- * Returns the name of this action.
+ * Returns the name of this procedure.
*
- * @return string Name of the action.
+ * @return string Name of the procedure.
*/
public function getName(): string {
return $this->name;
}
/**
- * Returns the handler for this action.
+ * Returns the handler for this procedure.
*
- * @return Closure Handler for this action.
+ * @return Closure Handler for this procedure.
*/
public function getHandler(): Closure {
return Closure::fromCallable($this->handler);
diff --git a/src/Server/RpcQuery.php b/src/Server/RpcQuery.php
index ceb4f31..e13232b 100644
--- a/src/Server/RpcQuery.php
+++ b/src/Server/RpcQuery.php
@@ -1,19 +1,19 @@
getMethod() === 'POST') {
@@ -46,11 +46,11 @@ class RpcRouteHandler implements RouteHandler {
if(!($content instanceof FormHttpContent))
return 400;
- $expectProcedure = true;
+ $expectAction = true;
$paramString = $content->getParamString();
$params = $content->getParams();
} elseif($request->getMethod() === 'GET') {
- $expectProcedure = false;
+ $expectAction = false;
$paramString = $request->getParamString();
$params = $request->getParams();
} else {
@@ -60,32 +60,32 @@ class RpcRouteHandler implements RouteHandler {
$response->setContentType('application/vnd.msgpack');
- $userToken = (string)$request->getHeaderLine('X-Aiwass-Verify');
+ $userToken = (string)$request->getHeaderLine('X-RPCii-Verify');
if($userToken === '') {
$response->setStatusCode(403);
- return AiwassMsgPack::encode(['error' => 'aiwass:verify']);
+ return RpciiMsgPack::encode(['error' => 'rpcii:verify']);
}
- $actInfo = $this->server->getActionInfo($action);
- if($actInfo === null) {
+ $procInfo = $this->server->getProcedureInfo($procedure);
+ if($procInfo === null) {
$response->setStatusCode(404);
- return AiwassMsgPack::encode(['error' => 'aiwass:unknown']);
+ return RpciiMsgPack::encode(['error' => 'rpcii:unknown']);
}
- if($actInfo->isProcedure() !== $expectProcedure) {
+ if($procInfo->isAction() !== $expectAction) {
$response->setStatusCode(405);
- $response->setHeader('Allow', $actInfo->isProcedure() ? 'POST' : 'GET');
- return AiwassMsgPack::encode(['error' => 'aiwass:method']);
+ $response->setHeader('Allow', $procInfo->isAction() ? 'POST' : 'GET');
+ return RpciiMsgPack::encode(['error' => 'rpcii:method']);
}
- if(!$this->verification->verify($userToken, $expectProcedure, $action, $paramString))
- return AiwassMsgPack::encode(['error' => 'aiwass:verify']);
+ if(!$this->verification->verify($userToken, $expectAction, $procedure, $paramString))
+ return RpciiMsgPack::encode(['error' => 'rpcii:verify']);
try {
- return AiwassMsgPack::encode($actInfo->invokeHandler($params));
+ return RpciiMsgPack::encode($procInfo->invokeHandler($params));
} catch(RuntimeException $ex) {
$response->setStatusCode(400);
- return AiwassMsgPack::encode(['error' => sprintf('aiwass:%s', $ex->getMessage())]);
+ return RpciiMsgPack::encode(['error' => sprintf('rpcii:%s', $ex->getMessage())]);
}
}
}
diff --git a/src/Server/RpcServer.php b/src/Server/RpcServer.php
index 0e2ae71..af598f3 100644
--- a/src/Server/RpcServer.php
+++ b/src/Server/RpcServer.php
@@ -1,45 +1,68 @@
*/
- private array $actions = [];
+interface RpcServer {
+ /**
+ * Creates a proxy for this RPC server with a specified namespace.
+ *
+ * @param string $prefix Prefix to apply to the scoped RPC server.
+ * @return RpcServer A scoped RPC server instance.
+ */
+ function scopeTo(string $prefix): RpcServer;
/**
- * Creates an RPC route handler.
+ * Registers a handler class.
*
- * @param IVerificationProvider $verification A verification provider.
- * @return RpcRouteHandler RPC route handler.
+ * @param RpcHandler $handler Handler to register.
*/
- public function createRouteHandler(IVerificationProvider $verification): RpcRouteHandler {
- return new RpcRouteHandler($this, $verification);
- }
+ function register(RpcHandler $handler): void;
- public function scopeTo(string $prefix): IRpcServer {
- return new RpcServerScoped($this, $prefix);
- }
+ /**
+ * Registers a procedure.
+ *
+ * @param bool $isAction true if the procedure is an action (HTTP POST), false if it is a query (HTTP GET).
+ * @param string $name Unique name of the procedure.
+ * @param callable $handler Handler for the procedure.
+ * @throws RuntimeException If a handler with the same name is already registered.
+ * @throws InvalidArgumentException If $handler is not a callable type.
+ */
+ function registerProcedure(bool $isAction, string $name, $handler): void;
- public function registerAction(bool $isProcedure, string $name, $handler): void {
- if(array_key_exists($name, $this->actions))
- throw new RuntimeException('an action with that name has already been registered');
+ /**
+ * Registers a query procedure (HTTP GET).
+ *
+ * @param string $name Unique name of the procedure.
+ * @param callable $handler Handler for the procedure.
+ * @throws RuntimeException If a handler with the same name is already registered.
+ * @throws InvalidArgumentException If $handler is not a callable type.
+ */
+ function registerQueryProcedure(string $name, $handler): void;
- $this->actions[$name] = new RpcActionInfo($isProcedure, $name, $handler);
- }
+ /**
+ * Registers an action procedure (HTTP POST).
+ *
+ * @param string $name Unique name of the procedure.
+ * @param callable $handler Handler for the procedure.
+ * @throws RuntimeException If a handler with the same name is already registered.
+ * @throws InvalidArgumentException If $handler is not a callable type.
+ */
+ function registerActionProcedure(string $name, $handler): void;
- public function getActionInfo(string $name): ?RpcActionInfo {
- return $this->actions[$name] ?? null;
- }
+ /**
+ * Retrieves information about an procedure.
+ *
+ * @param string $name Name of the procedure.
+ * @return ?RpcProcedureInfo An object containing information about the procedure, or null if it does not exist.
+ */
+ function getProcedureInfo(string $name): ?RpcProcedureInfo;
}
diff --git a/src/Server/RpcServerCommon.php b/src/Server/RpcServerCommon.php
new file mode 100644
index 0000000..033fab2
--- /dev/null
+++ b/src/Server/RpcServerCommon.php
@@ -0,0 +1,23 @@
+registerProcedures($this);
+ }
+
+ public function registerQueryProcedure(string $name, $handler): void {
+ $this->registerProcedure(false, $name, $handler);
+ }
+
+ public function registerActionProcedure(string $name, $handler): void {
+ $this->registerProcedure(true, $name, $handler);
+ }
+}
diff --git a/src/Server/RpcServerScoped.php b/src/Server/RpcServerScoped.php
deleted file mode 100644
index 6ca6b7d..0000000
--- a/src/Server/RpcServerScoped.php
+++ /dev/null
@@ -1,34 +0,0 @@
-base->scopeTo($this->prefix . $prefix);
- }
-
- public function registerAction(bool $isProcedure, string $name, $handler): void {
- $this->base->registerAction($isProcedure, $this->prefix . $name, $handler);
- }
-
- public function getActionInfo(string $name): ?RpcActionInfo {
- return $this->base->getActionInfo($this->prefix . $name);
- }
-}
diff --git a/src/Server/RpcServerTrait.php b/src/Server/RpcServerTrait.php
deleted file mode 100644
index 80ef6dd..0000000
--- a/src/Server/RpcServerTrait.php
+++ /dev/null
@@ -1,23 +0,0 @@
-registerRpcActions($this);
- }
-
- public function registerQueryAction(string $name, $handler): void {
- $this->registerAction(false, $name, $handler);
- }
-
- public function registerProcedureAction(string $name, $handler): void {
- $this->registerAction(true, $name, $handler);
- }
-}
diff --git a/src/Server/ScopedRpcServer.php b/src/Server/ScopedRpcServer.php
new file mode 100644
index 0000000..287ae7e
--- /dev/null
+++ b/src/Server/ScopedRpcServer.php
@@ -0,0 +1,34 @@
+base->scopeTo($this->prefix . $prefix);
+ }
+
+ public function registerProcedure(bool $isAction, string $name, $handler): void {
+ $this->base->registerProcedure($isAction, $this->prefix . $name, $handler);
+ }
+
+ public function getProcedureInfo(string $name): ?RpcProcedureInfo {
+ return $this->base->getProcedureInfo($this->prefix . $name);
+ }
+}
diff --git a/src/IVerificationProvider.php b/src/VerificationProvider.php
similarity index 70%
rename from src/IVerificationProvider.php
rename to src/VerificationProvider.php
index 7fb043c..a5ab4d7 100644
--- a/src/IVerificationProvider.php
+++ b/src/VerificationProvider.php
@@ -1,24 +1,24 @@
self->assertEquals('it is beans', $beans);
return 'query registered using action attribute';
}
#[RpcQuery('aiwass:test:query2')]
- public static function staticQueryRegisteredUsingQueryAttribute(string $required, string $optional = 'the') {
+ public static function staticQueryRegisteredUsingQueryAttribute(string $required, string $optional = 'the'): string {
self::$that->assertEquals('internet', $required);
self::$that->assertEquals('the', $optional);
return 'static query registered using query attribute';
}
- #[RpcProcedure('aiwass:test:proc2')]
- public function dynamicProcedureRegisteredUsingProcedureAttribute(string $optional = 'meow') {
+ #[RpcAction('aiwass:test:proc2')]
+ public function dynamicProcedureRegisteredUsingProcedureAttribute(string $optional = 'meow'): string {
$this->self->assertEquals('meow', $optional);
return 'dynamic procedure registered using procedure attribute';
}
#[RpcQuery('aiwass:test:query3')]
- #[RpcProcedure('aiwass:test:proc3')]
- public function multiple() {
+ #[RpcAction('aiwass:test:proc3')]
+ public function multiple(): string {
return 'a dynamic method registered as both a query and a procedure';
}
- public function hasNoAttr() {
+ public function hasNoAttr(): string {
return 'not an action handler';
}
};
- $server = new RpcServer;
+ $server = new HttpRpcServer;
$server->register($handler);
- $this->assertNull($server->getActionInfo('aiwass:none'));
+ $this->assertNull($server->getProcedureInfo('aiwass:none'));
- $proc1 = $server->getActionInfo('aiwass:test:proc1');
- $this->assertNotNull($proc1);
- $this->assertTrue($proc1->isProcedure());
- $this->assertEquals('aiwass:test:proc1', $proc1->getName());
- $this->assertEquals('procedure registered using action attribute', $proc1->invokeHandler());
+ $act1 = $server->getProcedureInfo('aiwass:test:proc1');
+ $this->assertNotNull($act1);
+ $this->assertTrue($act1->isAction());
+ $this->assertEquals('aiwass:test:proc1', $act1->getName());
+ $this->assertEquals('procedure registered using action attribute', $act1->invokeHandler());
- $proc2 = $server->getActionInfo('aiwass:test:proc2');
- $this->assertNotNull($proc2);
- $this->assertTrue($proc2->isProcedure());
- $this->assertEquals('aiwass:test:proc2', $proc2->getName());
- $this->assertEquals('dynamic procedure registered using procedure attribute', $proc2->invokeHandler());
+ $act2 = $server->getProcedureInfo('aiwass:test:proc2');
+ $this->assertNotNull($act2);
+ $this->assertTrue($act2->isAction());
+ $this->assertEquals('aiwass:test:proc2', $act2->getName());
+ $this->assertEquals('dynamic procedure registered using procedure attribute', $act2->invokeHandler());
- $query1 = $server->getActionInfo('aiwass:test:query1');
+ $query1 = $server->getProcedureInfo('aiwass:test:query1');
$this->assertNotNull($query1);
- $this->assertFalse($query1->isProcedure());
+ $this->assertFalse($query1->isAction());
$this->assertEquals('aiwass:test:query1', $query1->getName());
$this->assertEquals('query registered using action attribute', $query1->invokeHandler(['beans' => 'it is beans']));
- $query2 = $server->getActionInfo('aiwass:test:query2');
+ $query2 = $server->getProcedureInfo('aiwass:test:query2');
$this->assertNotNull($query2);
- $this->assertFalse($query2->isProcedure());
+ $this->assertFalse($query2->isAction());
$this->assertEquals('aiwass:test:query2', $query2->getName());
$this->assertEquals('static query registered using query attribute', $query2->invokeHandler(['required' => 'internet']));
- $query3 = $server->getActionInfo('aiwass:test:query3');
- $proc3 = $server->getActionInfo('aiwass:test:proc3');
+ $query3 = $server->getProcedureInfo('aiwass:test:query3');
+ $proc3 = $server->getProcedureInfo('aiwass:test:proc3');
$this->assertNotNull($query3);
$this->assertNotNull($proc3);
- $this->assertFalse($query3->isProcedure());
- $this->asserttrue($proc3->isProcedure());
+ $this->assertFalse($query3->isAction());
+ $this->asserttrue($proc3->isAction());
$this->assertEquals('aiwass:test:query3', $query3->getName());
$this->assertEquals('aiwass:test:proc3', $proc3->getName());
$this->assertEquals($query3->getHandler(), $proc3->getHandler());
$this->assertEquals('a dynamic method registered as both a query and a procedure', $query3->invokeHandler());
$this->assertEquals('a dynamic method registered as both a query and a procedure', $proc3->invokeHandler());
- $this->assertNull($server->getActionInfo('doesnotexist'));
+ $this->assertNull($server->getProcedureInfo('doesnotexist'));
$this->expectException(RuntimeException::class);
$query1->invokeHandler(['notbeans' => 'it is not beans']);
diff --git a/tests/CurlHttpTest.php b/tests/CurlHttpTest.php
index ed58749..5cad96c 100644
--- a/tests/CurlHttpTest.php
+++ b/tests/CurlHttpTest.php
@@ -1,13 +1,13 @@
setParams('soap=beans');
$response = json_decode($request->execute(), true);
- $this->assertTrue(array_key_exists('X-Test', $response['headers']));
+ $this->assertIsArray($response);
+ $this->assertArrayHasKey('headers', $response);
+ $this->assertIsArray($response['headers']);
+ $this->assertArrayHasKey('X-Test', $response['headers']);
$this->assertEquals('teste', $response['headers']['X-Test']);
- $this->assertTrue(array_key_exists('alreadyhere', $response['args']));
+ $this->assertArrayHasKey('args', $response);
+ $this->assertIsArray($response['args']);
+ $this->assertArrayHasKey('alreadyhere', $response['args']);
$this->assertEquals('true', $response['args']['alreadyhere']);
- $this->assertTrue(array_key_exists('soap', $response['args']));
+ $this->assertArrayHasKey('soap', $response['args']);
$this->assertEquals('beans', $response['args']['soap']);
}
@@ -37,13 +42,18 @@ final class CurlHttpTest extends TestCase {
$request->setParams('windows=xp&macos=leopard');
$response = json_decode($request->execute(), true);
- $this->assertTrue(array_key_exists('X-Meow', $response['headers']));
+ $this->assertIsArray($response);
+ $this->assertArrayHasKey('headers', $response);
+ $this->assertIsArray($response['headers']);
+ $this->assertArrayHasKey('X-Meow', $response['headers']);
$this->assertEquals('soap', $response['headers']['X-Meow']);
- $this->assertTrue(array_key_exists('windows', $response['form']));
+ $this->assertArrayHasKey('form', $response);
+ $this->assertIsArray($response['form']);
+ $this->assertArrayHasKey('windows', $response['form']);
$this->assertEquals('xp', $response['form']['windows']);
- $this->assertTrue(array_key_exists('macos', $response['form']));
+ $this->assertArrayHasKey('macos', $response['form']);
$this->assertEquals('leopard', $response['form']['macos']);
}
}
diff --git a/tests/HmacVerificationTest.php b/tests/HmacVerificationTest.php
index e1b1ef5..89ac793 100644
--- a/tests/HmacVerificationTest.php
+++ b/tests/HmacVerificationTest.php
@@ -1,27 +1,27 @@
'meow');
- $action = 'test';
+ $procedure = 'test';
$params = 'meow=cool&the=bean';
- $queryToken = $provider->sign(false, $action, $params);
- $this->assertTrue($provider->verify($queryToken, false, $action, $params));
- $this->assertFalse($provider->verify($queryToken, true, $action, $params));
+ $queryToken = $provider->sign(false, $procedure, $params);
+ $this->assertTrue($provider->verify($queryToken, false, $procedure, $params));
+ $this->assertFalse($provider->verify($queryToken, true, $procedure, $params));
- $procedureToken = $provider->sign(true, $action, $params);
- $this->assertTrue($provider->verify($procedureToken, true, $action, $params));
- $this->assertFalse($provider->verify($procedureToken, false, $action, $params));
+ $actionToken = $provider->sign(true, $procedure, $params);
+ $this->assertTrue($provider->verify($actionToken, true, $procedure, $params));
+ $this->assertFalse($provider->verify($actionToken, false, $procedure, $params));
}
}
diff --git a/tests/ScopedServerTest.php b/tests/ScopedServerTest.php
index 6db0e62..3ee0123 100644
--- a/tests/ScopedServerTest.php
+++ b/tests/ScopedServerTest.php
@@ -1,40 +1,40 @@
registerQueryAction('test', fn() => 'test');
+ $base = new HttpRpcServer;
+ $base->registerQueryProcedure('test', fn() => 'test');
$scopedToBeans = $base->scopeTo('beans:');
- $scopedToBeans->registerQueryAction('test', fn() => 'test in beans');
+ $scopedToBeans->registerQueryProcedure('test', fn() => 'test in beans');
$scopedToGarf = $base->scopeTo('garf:');
$scopedToGarfield = $scopedToGarf->scopeTo('ield:');
- $scopedToGarfield->registerQueryAction('test', fn() => 'test in garfield');
+ $scopedToGarfield->registerQueryProcedure('test', fn() => 'test in garfield');
- $baseTest = $base->getActionInfo('test');
+ $baseTest = $base->getProcedureInfo('test');
$this->assertNotNull($baseTest);
$this->assertEquals('test', $baseTest->getName());
- $baseBeansTest = $base->getActionInfo('beans:test');
- $scopedBeansTest = $scopedToBeans->getActionInfo('test');
+ $baseBeansTest = $base->getProcedureInfo('beans:test');
+ $scopedBeansTest = $scopedToBeans->getProcedureInfo('test');
$this->assertNotNull($baseBeansTest);
$this->assertSame($baseBeansTest, $scopedBeansTest);
$this->assertEquals('beans:test', $scopedBeansTest->getName());
- $baseGarfieldTest = $base->getActionInfo('garf:ield:test');
- $scopedGarfieldTest = $scopedToGarfield->getActionInfo('test');
+ $baseGarfieldTest = $base->getProcedureInfo('garf:ield:test');
+ $scopedGarfieldTest = $scopedToGarfield->getProcedureInfo('test');
$this->assertNotNull($baseGarfieldTest);
$this->assertSame($baseGarfieldTest, $scopedGarfieldTest);
$this->assertEquals('garf:ield:test', $scopedGarfieldTest->getName());
diff --git a/tests/StreamHttpTest.php b/tests/StreamHttpTest.php
new file mode 100644
index 0000000..23eba69
--- /dev/null
+++ b/tests/StreamHttpTest.php
@@ -0,0 +1,59 @@
+setPost(false);
+ $request->setUrl('https://httpbin.org/get?alreadyhere=true');
+ $request->setHeader('X-Test', 'teste');
+ $request->setParams('soap=beans');
+ $response = json_decode($request->execute(), true);
+
+ $this->assertIsArray($response);
+ $this->assertArrayHasKey('headers', $response);
+ $this->assertIsArray($response['headers']);
+ $this->assertArrayHasKey('X-Test', $response['headers']);
+ $this->assertEquals('teste', $response['headers']['X-Test']);
+
+ $this->assertArrayHasKey('args', $response);
+ $this->assertIsArray($response['args']);
+ $this->assertArrayHasKey('alreadyhere', $response['args']);
+ $this->assertEquals('true', $response['args']['alreadyhere']);
+
+ $this->assertArrayHasKey('soap', $response['args']);
+ $this->assertEquals('beans', $response['args']['soap']);
+ }
+
+ public function testPostRequest(): void {
+ $request = new StreamHttpRequest;
+ $request->setPost(true);
+ $request->setUrl('https://httpbin.org/post');
+ $request->setHeader('X-Meow', 'soap');
+ $request->setParams('windows=xp&macos=leopard');
+ $response = json_decode($request->execute(), true);
+
+ $this->assertIsArray($response);
+ $this->assertArrayHasKey('headers', $response);
+ $this->assertIsArray($response['headers']);
+ $this->assertArrayHasKey('X-Meow', $response['headers']);
+ $this->assertEquals('soap', $response['headers']['X-Meow']);
+
+ $this->assertArrayHasKey('form', $response);
+ $this->assertIsArray($response['form']);
+ $this->assertArrayHasKey('windows', $response['form']);
+ $this->assertEquals('xp', $response['form']['windows']);
+
+ $this->assertArrayHasKey('macos', $response['form']);
+ $this->assertEquals('leopard', $response['form']['macos']);
+ }
+}