From ba0ebc90e5839544b84b57bc2e0353123a6bfffb Mon Sep 17 00:00:00 2001 From: Rob Landers Date: Sun, 30 May 2021 21:28:30 +0200 Subject: [PATCH 1/4] Add a centralized dapr client --- composer.json | 7 +- composer.lock | 529 +++++++++++++++++---- psysh-bootstrap.php | 3 + psysh-config.php | 6 + src/lib/Client/BindingRequest.php | 18 + src/lib/Client/BindingResponse.php | 21 + src/lib/Client/DaprClient.php | 401 ++++++++++++++++ src/lib/Client/DaprClientBuilder.php | 56 +++ src/lib/Client/DaprHttpClient.php | 125 +++++ src/lib/Client/HttpSecretsTrait.php | 59 +++ src/lib/Client/HttpStateTrait.php | 253 ++++++++++ src/lib/Client/PromiseHandlingTrait.php | 42 ++ src/lib/Client/StateTransactionRequest.php | 31 ++ 13 files changed, 1448 insertions(+), 103 deletions(-) create mode 100644 psysh-bootstrap.php create mode 100644 psysh-config.php create mode 100644 src/lib/Client/BindingRequest.php create mode 100644 src/lib/Client/BindingResponse.php create mode 100644 src/lib/Client/DaprClient.php create mode 100644 src/lib/Client/DaprClientBuilder.php create mode 100644 src/lib/Client/DaprHttpClient.php create mode 100644 src/lib/Client/HttpSecretsTrait.php create mode 100644 src/lib/Client/HttpStateTrait.php create mode 100644 src/lib/Client/PromiseHandlingTrait.php create mode 100644 src/lib/Client/StateTransactionRequest.php diff --git a/composer.json b/composer.json index aa2511a..562174e 100644 --- a/composer.json +++ b/composer.json @@ -22,12 +22,13 @@ "nyholm/psr7": "^1.3", "nyholm/psr7-server": "^1.0", "php-di/invoker": "^2.3", - "laminas/laminas-httphandlerrunner": "^1.3" + "laminas/laminas-httphandlerrunner": "^1.3", + "guzzlehttp/guzzle": "^7.3" }, "require-dev": { "ext-xdebug": "*", - "vimeo/psalm": "^4.3", - "phpunit/phpunit": "^9" + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4.7" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 812ed33..319e916 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,241 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "134e7fb90030dbe4d74d0040df5e30aa", + "content-hash": "85ced5d23be1490857510342cfe4c785", "packages": [ + { + "name": "guzzlehttp/guzzle", + "version": "7.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7008573787b430c1c1f650e3722d9bba59967628" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", + "reference": "7008573787b430c1c1f650e3722d9bba59967628", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7 || ^2.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.3-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://github.com/alexeyshockov", + "type": "github" + }, + { + "url": "https://github.com/gmponos", + "type": "github" + } + ], + "time": "2021-03-23T11:33:13+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.1" + }, + "time": "2021-03-07T09:25:29+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.8.2" + }, + "time": "2021-04-26T09:17:50+00:00" + }, { "name": "laminas/laminas-httphandlerrunner", "version": "1.4.0", @@ -517,16 +750,16 @@ }, { "name": "nyholm/psr7-server", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/Nyholm/psr7-server.git", - "reference": "5c134aeb5dd6521c7978798663470dabf0528c96" + "reference": "b846a689844cef114e8079d8c80f0afd96745ae3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/5c134aeb5dd6521c7978798663470dabf0528c96", - "reference": "5c134aeb5dd6521c7978798663470dabf0528c96", + "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/b846a689844cef114e8079d8c80f0afd96745ae3", + "reference": "b846a689844cef114e8079d8c80f0afd96745ae3", "shasum": "" }, "require": { @@ -567,7 +800,7 @@ ], "support": { "issues": "https://github.com/Nyholm/psr7-server/issues", - "source": "https://github.com/Nyholm/psr7-server/tree/1.0.1" + "source": "https://github.com/Nyholm/psr7-server/tree/1.0.2" }, "funding": [ { @@ -579,7 +812,7 @@ "type": "github" } ], - "time": "2020-11-15T15:26:20+00:00" + "time": "2021-05-12T11:11:27+00:00" }, { "name": "opis/closure", @@ -921,6 +1154,58 @@ }, "time": "2021-03-05T17:36:06+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, { "name": "psr/http-factory", "version": "1.0.1", @@ -1088,16 +1373,16 @@ }, { "name": "psr/log", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -1121,7 +1406,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -1132,9 +1417,53 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2020-03-23T09:12:05+00:00" + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" } ], "packages-dev": [ @@ -1306,16 +1635,16 @@ }, { "name": "composer/package-versions-deprecated", - "version": "1.11.99.1", + "version": "1.11.99.2", "source": { "type": "git", "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6" + "reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/7413f0b55a051e89485c5cb9f765fe24bb02a7b6", - "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/c6522afe5540d5fc46675043d3ed5a45a740b27c", + "reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c", "shasum": "" }, "require": { @@ -1359,7 +1688,7 @@ "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", "support": { "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.1" + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.2" }, "funding": [ { @@ -1375,20 +1704,20 @@ "type": "tidelift" } ], - "time": "2020-11-11T10:22:58+00:00" + "time": "2021-05-24T07:46:03+00:00" }, { "name": "composer/semver", - "version": "3.2.4", + "version": "3.2.5", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464" + "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", - "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", + "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9", + "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9", "shasum": "" }, "require": { @@ -1440,7 +1769,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.4" + "source": "https://github.com/composer/semver/tree/3.2.5" }, "funding": [ { @@ -1456,20 +1785,20 @@ "type": "tidelift" } ], - "time": "2020-11-13T08:59:24+00:00" + "time": "2021-05-24T12:41:47+00:00" }, { "name": "composer/xdebug-handler", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "31d57697eb1971712a08031cfaff5a846d10bdf5" + "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/31d57697eb1971712a08031cfaff5a846d10bdf5", - "reference": "31d57697eb1971712a08031cfaff5a846d10bdf5", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/964adcdd3a28bf9ed5d9ac6450064e0d71ed7496", + "reference": "964adcdd3a28bf9ed5d9ac6450064e0d71ed7496", "shasum": "" }, "require": { @@ -1504,7 +1833,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.0" + "source": "https://github.com/composer/xdebug-handler/tree/2.0.1" }, "funding": [ { @@ -1520,7 +1849,7 @@ "type": "tidelift" } ], - "time": "2021-04-09T19:40:06+00:00" + "time": "2021-05-05T19:37:51+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -1840,16 +2169,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.10.4", + "version": "v4.10.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f", + "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f", "shasum": "" }, "require": { @@ -1890,9 +2219,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5" }, - "time": "2020-12-20T10:01:03+00:00" + "time": "2021-05-03T19:11:20+00:00" }, { "name": "openlss/lib-array2xml", @@ -3670,16 +3999,16 @@ }, { "name": "symfony/console", - "version": "v5.2.7", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "90374b8ed059325b49a29b55b3f8bb4062c87629" + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/90374b8ed059325b49a29b55b3f8bb4062c87629", - "reference": "90374b8ed059325b49a29b55b3f8bb4062c87629", + "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", "shasum": "" }, "require": { @@ -3747,7 +4076,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.7" + "source": "https://github.com/symfony/console/tree/v5.2.8" }, "funding": [ { @@ -3763,20 +4092,20 @@ "type": "tidelift" } ], - "time": "2021-04-19T14:07:32+00:00" + "time": "2021-05-11T15:45:21+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", "shasum": "" }, "require": { @@ -3788,7 +4117,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3826,7 +4155,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" }, "funding": [ { @@ -3842,20 +4171,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170" + "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170", - "reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab", + "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab", "shasum": "" }, "require": { @@ -3867,7 +4196,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3907,7 +4236,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0" }, "funding": [ { @@ -3923,20 +4252,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-27T09:17:38+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248" + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { @@ -3948,7 +4277,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3991,7 +4320,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" }, "funding": [ { @@ -4007,20 +4336,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", - "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1", + "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1", "shasum": "" }, "require": { @@ -4032,7 +4361,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4071,7 +4400,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0" }, "funding": [ { @@ -4087,20 +4416,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-27T09:27:20+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010", "shasum": "" }, "require": { @@ -4109,7 +4438,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4150,7 +4479,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" }, "funding": [ { @@ -4166,20 +4495,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", "shasum": "" }, "require": { @@ -4188,7 +4517,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4233,7 +4562,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" }, "funding": [ { @@ -4249,7 +4578,7 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/service-contracts", @@ -4332,16 +4661,16 @@ }, { "name": "symfony/string", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", "shasum": "" }, "require": { @@ -4395,7 +4724,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.6" + "source": "https://github.com/symfony/string/tree/v5.2.8" }, "funding": [ { @@ -4411,7 +4740,7 @@ "type": "tidelift" } ], - "time": "2021-03-17T17:12:15+00:00" + "time": "2021-05-10T14:56:10+00:00" }, { "name": "theseer/tokenizer", @@ -4465,16 +4794,16 @@ }, { "name": "vimeo/psalm", - "version": "4.7.2", + "version": "4.7.3", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "83a0325c0a95c0ab531d6b90c877068b464377b5" + "reference": "38c452ae584467e939d55377aaf83b5a26f19dd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/83a0325c0a95c0ab531d6b90c877068b464377b5", - "reference": "83a0325c0a95c0ab531d6b90c877068b464377b5", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/38c452ae584467e939d55377aaf83b5a26f19dd1", + "reference": "38c452ae584467e939d55377aaf83b5a26f19dd1", "shasum": "" }, "require": { @@ -4493,7 +4822,7 @@ "felixfbecker/advanced-json-rpc": "^3.0.3", "felixfbecker/language-server-protocol": "^1.5", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.10.1", + "nikic/php-parser": "^4.10.5", "openlss/lib-array2xml": "^1.0", "php": "^7.1|^8", "sebastian/diff": "^3.0 || ^4.0", @@ -4513,7 +4842,7 @@ "phpspec/prophecy": ">=1.9.0", "phpunit/phpunit": "^9.0", "psalm/plugin-phpunit": "^0.13", - "slevomat/coding-standard": "^6.3.11", + "slevomat/coding-standard": "^7.0", "squizlabs/php_codesniffer": "^3.5", "symfony/process": "^4.3", "weirdan/phpunit-appveyor-reporter": "^1.0.0", @@ -4564,9 +4893,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.7.2" + "source": "https://github.com/vimeo/psalm/tree/4.7.3" }, - "time": "2021-05-01T20:56:25+00:00" + "time": "2021-05-24T04:09:51+00:00" }, { "name": "webmozart/assert", diff --git a/psysh-bootstrap.php b/psysh-bootstrap.php new file mode 100644 index 0000000..28335e9 --- /dev/null +++ b/psysh-bootstrap.php @@ -0,0 +1,3 @@ +build(); diff --git a/psysh-config.php b/psysh-config.php new file mode 100644 index 0000000..a60c4e2 --- /dev/null +++ b/psysh-config.php @@ -0,0 +1,6 @@ + [__DIR__ . '/vendor/autoload.php', __DIR__ . '/psysh-bootstrap.php'], + 'startupMessage' => sprintf('$client configured') +]; diff --git a/src/lib/Client/BindingRequest.php b/src/lib/Client/BindingRequest.php new file mode 100644 index 0000000..22473e5 --- /dev/null +++ b/src/lib/Client/BindingRequest.php @@ -0,0 +1,18 @@ + $metadata + */ + public function __construct(public BindingRequest $request, public mixed $data, public array $metadata) + { + } +} diff --git a/src/lib/Client/DaprClient.php b/src/lib/Client/DaprClient.php new file mode 100644 index 0000000..87a3dce --- /dev/null +++ b/src/lib/Client/DaprClient.php @@ -0,0 +1,401 @@ +|'array'|'int'|'string'|'float' $dataType + * @param BindingRequest $bindingRequest + * @param string $dataType + * @return BindingResponse + */ + abstract public function invokeBinding( + BindingRequest $bindingRequest, + string $dataType = 'array' + ): BindingResponse; + + /** + * @template T + * @psalm-param class-string|'array'|'int'|'string'|'float' $dataType + * @param BindingRequest $bindingRequest + * @param string $dataType + * @return PromiseInterface> + */ + abstract public function invokeBindingAsync( + BindingRequest $bindingRequest, + string $dataType = 'array' + ): PromiseInterface; + + /** + * @template T + * @param string $bindingName + * @param string $operation + * @param T $data + * @param array $metadata + * @return BindingRequest + */ + public function createInvokeBindingRequest( + string $bindingName, + string $operation, + mixed $data, + array $metadata = [] + ): BindingRequest { + return new BindingRequest($bindingName, $operation, $this->serializer->as_json($data), $metadata); + } + + /** + * @template T + * @param string $pubsubName + * @param string $topicName + * @param T $data + * @param array $metadata + */ + abstract public function publishEvent( + string $pubsubName, + string $topicName, + mixed $data, + array $metadata = [] + ): void; + + /** + * @template T + * @param string $pubsubName + * @param string $topicName + * @param T $data + * @param array $metadata + * @return PromiseInterface + */ + abstract public function publishEventAsync( + string $pubsubName, + string $topicName, + mixed $data, + array $metadata = [] + ): PromiseInterface; + + /** + * @template T + * @param string $httpMethod + * @param string $appId + * @param string $methodName + * @param T|null $data + * @param array $metadata + * @return ResponseInterface + */ + abstract public function invokeMethod( + string $httpMethod, + string $appId, + string $methodName, + mixed $data = null, + array $metadata = [] + ): ResponseInterface; + + /** + * @template T + * @param string $httpMethod + * @param string $appId + * @param string $methodName + * @param T|null $data + * @param array $metadata + * @return PromiseInterface + */ + abstract public function invokeMethodAsync( + string $httpMethod, + string $appId, + string $methodName, + mixed $data = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @template T + * @psalm-param class-string|'array'|'int'|'string'|'float' $asType + * @param string $storeName + * @param string $key + * @param string $asType + * @param Consistency|null $consistency + * @param array $metadata + * @return PromiseInterface + */ + abstract public function getStateAsync( + string $storeName, + string $key, + string $asType = 'array', + Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @template T + * @psalm-param class-string|'array'|'int'|'string'|'float' $asType + * @param string $storeName + * @param string $key + * @param string $asType + * @param Consistency|null $consistency + * @param array $metadata + * @return T + */ + abstract public function getState( + string $storeName, + string $key, + string $asType = 'array', + Consistency $consistency = null, + array $metadata = [] + ): mixed; + + /** + * @template T + * @param string $storeName + * @param string $key + * @param T $value + * @param Consistency|null $consistency + * @param array $metadata + * @return PromiseInterface + */ + abstract public function saveStateAsync( + string $storeName, + string $key, + mixed $value, + Consistency|null $consistency = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @template T + * @param string $storeName + * @param string $key + * @param T $value + * @param Consistency|null $consistency + * @param array $metadata + */ + abstract public function saveState( + string $storeName, + string $key, + mixed $value, + Consistency|null $consistency = null, + array $metadata = [] + ): void; + + /** + * @template T + * @param string $storeName + * @param string $key + * @param T $value + * @param string $etag + * @param Consistency|null $consistency + * @param array $metadata + * @return PromiseInterface + */ + abstract public function trySaveStateAsync( + string $storeName, + string $key, + mixed $value, + string $etag, + Consistency|null $consistency = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @template T + * @param string $storeName + * @param string $key + * @param T $value + * @param string $etag + * @param Consistency|null $consistency + * @param array $metadata + * @return bool + */ + abstract public function trySaveState( + string $storeName, + string $key, + mixed $value, + string $etag, + Consistency|null $consistency = null, + array $metadata = [] + ): bool; + + /** + * @template T + * @psalm-param class-string|'array'|'int'|'string'|'float' $asType + * @param string $storeName + * @param string $key + * @param string $asType + * @param Consistency|null $consistency + * @param array $metadata + * @return PromiseInterface + */ + abstract public function getStateAndEtagAsync( + string $storeName, + string $key, + string $asType = 'array', + Consistency|null $consistency = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @template T + * @psalm-param class-string|'array'|'int'|'string'|'float' $asType + * @param string $storeName + * @param string $key + * @param string $asType + * @param Consistency|null $consistency + * @param array $metadata + * @return array{value: T, etag: string} + */ + abstract public function getStateAndEtag( + string $storeName, + string $key, + string $asType = 'array', + Consistency|null $consistency = null, + array $metadata = [] + ): array; + + /** + * @param string $storeName + * @param StateTransactionRequest[] $operations + * @param array $metadata + */ + abstract public function executeStateTransaction(string $storeName, array $operations, array $metadata = []): void; + + /** + * @param string $storeName + * @param StateTransactionRequest[] $operations + * @param array $metadata + * @return PromiseInterface + */ + abstract public function executeStateTransactionAsync( + string $storeName, + array $operations, + array $metadata = [] + ): PromiseInterface; + + /** + * @param string $storeName + * @param string $key + * @param Consistency|null $consistency + * @param array $metadata + * @return PromiseInterface + */ + abstract public function deleteStateAsync( + string $storeName, + string $key, + Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @param string $storeName + * @param string $key + * @param Consistency|null $consistency + * @param array $metadata + */ + abstract public function deleteState( + string $storeName, + string $key, + Consistency $consistency = null, + array $metadata = [] + ): void; + + /** + * @param string $storeName + * @param string $key + * @param string $etag + * @param Consistency|null $consistency + * @param array $metadata + * @return PromiseInterface + */ + abstract public function tryDeleteStateAsync( + string $storeName, + string $key, + string $etag, + Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface; + + /** + * @param string $storeName + * @param string $key + * @param string $etag + * @param Consistency|null $consistency + * @param array $metadata + * @return bool + */ + abstract public function tryDeleteState( + string $storeName, + string $key, + string $etag, + Consistency $consistency = null, + array $metadata = [] + ): bool; + + /** + * @param string $storeName + * @param string $key + * @param array $metadata + * @return PromiseInterface> + */ + abstract public function getSecretAsync(string $storeName, string $key, array $metadata = []): PromiseInterface; + + /** + * @param string $storeName + * @param string $key + * @param array $metadata + * @return array + */ + abstract public function getSecret(string $storeName, string $key, array $metadata = []): array; + + /** + * @param string $storeName + * @param array $metadata + * @return PromiseInterface>> + */ + abstract public function getBulkSecretAsync(string $storeName, array $metadata = []): PromiseInterface; + + /** + * @param string $storeName + * @param array $metadata + * @return array> + */ + abstract public function getBulkSecret(string $storeName, array $metadata = []): array; + + /** + * @param string $token + * @return null|array{dapr-api-token: string} + */ + protected function getDaprApiToken(string $token): array|null + { + if (empty($token)) { + return null; + } + + return ['dapr-api-token' => $token]; + } +} diff --git a/src/lib/Client/DaprClientBuilder.php b/src/lib/Client/DaprClientBuilder.php new file mode 100644 index 0000000..583d23f --- /dev/null +++ b/src/lib/Client/DaprClientBuilder.php @@ -0,0 +1,56 @@ +deserializationConfig, $this->serializationConfig, $this->logger); + } + + public function withSerializationConfig(SerializationConfig $serializationConfig): self + { + return new self($this->defaultHttpHost, $this->deserializationConfig, $serializationConfig, $this->logger); + } + + public function withDeserializationConfig(DeserializationConfig $deserializationConfig): self + { + return new self($this->defaultHttpHost, $deserializationConfig, $this->serializationConfig, $this->logger); + } + + public function withLogger(LoggerInterface $logger): self + { + return new self($this->defaultHttpHost, $this->deserializationConfig, $this->serializationConfig, $logger); + } + + public function build(): DaprClient + { + return new DaprHttpClient( + $this->defaultHttpHost, + new Deserializer($this->deserializationConfig, $this->logger), + new Serializer($this->serializationConfig, $this->logger) + ); + } +} diff --git a/src/lib/Client/DaprHttpClient.php b/src/lib/Client/DaprHttpClient.php new file mode 100644 index 0000000..cab220d --- /dev/null +++ b/src/lib/Client/DaprHttpClient.php @@ -0,0 +1,125 @@ +baseHttpUri, '/')) { + $this->baseHttpUri = rtrim($this->baseHttpUri, '/'); + } + $this->httpClient = new Client( + [ + 'base_uri' => $this->baseHttpUri, + 'allow_redirects' => false, + 'headers' => [ + 'User-Agent' => 'DaprPHPSDK/v2.0', + 'Accept' => 'application/json', + 'Content-Type' => 'application/json' + ] + ] + ); + } + + /** + * @throws DaprException + */ + public function invokeBinding(BindingRequest $bindingRequest, string $dataType = 'array'): BindingResponse + { + return $this->invokeBindingAsync($bindingRequest, $dataType)->wait(); + } + + public function invokeBindingAsync(BindingRequest $bindingRequest, string $dataType = 'array'): PromiseInterface + { + return $this->handlePromise( + $this->httpClient->putAsync( + '/v1.0/bindings/' . $bindingRequest->bindingName, + [ + 'body' => $this->serializer->as_json( + [ + 'data' => $bindingRequest->data, + 'metadata' => $bindingRequest->metadata, + 'operation' => $bindingRequest->operation + ] + ) + ] + ), + fn(ResponseInterface $response) => new BindingResponse( + $bindingRequest, + $this->deserializer->from_json($dataType, $response->getBody()->getContents()), + $response->getHeaders() + ) + ); + } + + /** + * @throws DaprException + */ + public function publishEvent(string $pubsubName, string $topicName, mixed $data, array $metadata = []): void + { + $this->publishEventAsync($pubsubName, $topicName, $data, $metadata)->wait(); + } + + public function publishEventAsync( + string $pubsubName, + string $topicName, + mixed $data, + array $metadata = [] + ): PromiseInterface { + $options = [ + 'query' => $metadata, + 'body' => $this->serializer->as_json($data) + ]; + return $this->handlePromise($this->httpClient->postAsync("/v1.0/publish/$pubsubName/$topicName", $options)); + } + + /** + * @throws DaprException + */ + public function invokeMethod( + string $httpMethod, + string $appId, + string $methodName, + mixed $data = null, + array $metadata = [] + ): ResponseInterface { + return $this->handlePromise( + $this->invokeMethodAsync($httpMethod, $appId, $methodName, $data, $metadata) + )->wait(); + } + + public function invokeMethodAsync( + string $httpMethod, + string $appId, + string $methodName, + mixed $data = null, + array $metadata = [] + ): PromiseInterface { + $options = []; + if (!empty($data)) { + $options['body'] = $this->serializer->as_json($data); + } + $options['headers'] = $metadata; + return $this->handlePromise( + $this->httpClient->requestAsync($httpMethod, "/v1.0/invoke/$appId/$methodName", $options) + ); + } +} diff --git a/src/lib/Client/HttpSecretsTrait.php b/src/lib/Client/HttpSecretsTrait.php new file mode 100644 index 0000000..5d7f9e7 --- /dev/null +++ b/src/lib/Client/HttpSecretsTrait.php @@ -0,0 +1,59 @@ +getSecretAsync($storeName, $key, $metadata)->wait(); + } + + public function getSecretAsync(string $storeName, string $key, array $metadata = []): PromiseInterface + { + return $this->handlePromise( + $this->httpClient->getAsync("/v1.0/secrets/$storeName/$key", ['query' => $metadata]), + fn(ResponseInterface $response) => $this->deserializer->from_json( + 'array', + $response->getBody()->getContents() + ) + ); + } + + public function getBulkSecret(string $storeName, array $metadata = []): array + { + return $this->getBulkSecretAsync($storeName, $metadata)->wait(); + } + + public function getBulkSecretAsync(string $storeName, array $metadata = []): PromiseInterface + { + return $this->handlePromise( + $this->httpClient->getAsync( + "/v1.0/secrets/$storeName/bulk", + [ + 'query' => $metadata + ] + ), + fn(ResponseInterface $response) => $this->deserializer->from_json( + 'array', + $response->getBody()->getContents() + ) + ); + } +} diff --git a/src/lib/Client/HttpStateTrait.php b/src/lib/Client/HttpStateTrait.php new file mode 100644 index 0000000..832b6d1 --- /dev/null +++ b/src/lib/Client/HttpStateTrait.php @@ -0,0 +1,253 @@ +getStateAsync($storeName, $key, $asType, $consistency, $metadata)->wait(); + } + + public function getStateAsync( + string $storeName, + string $key, + string $asType = 'array', + Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface { + return $this->handlePromise( + $this->getStateAndEtagAsync($storeName, $key, $asType, $consistency, $metadata), + fn(array $result) => $result['value'] + ); + } + + public function getStateAndEtagAsync( + string $storeName, + string $key, + string $asType = 'array', + ?Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface { + $options = []; + if (!empty($consistency)) { + $options['consistency'] = $consistency->get_consistency(); + $options['concurrency'] = $consistency->get_concurrency(); + } + $options = array_merge($options, $metadata); + return $this->handlePromise( + $this->httpClient->getAsync( + "/v1.0/state/$storeName/$key", + [ + 'query' => $options + ] + ), + fn(ResponseInterface $response) => [ + 'value' => $this->deserializer->from_json( + $asType, + $response->getBody()->getContents() + ), + 'etag' => $response->getHeader('Etag')[0] ?? '' + ] + ); + } + + public function saveState( + string $storeName, + string $key, + mixed $value, + ?Consistency $consistency = null, + array $metadata = [] + ): void { + $this->saveStateAsync($storeName, $key, $value, $consistency, $metadata)->wait(); + } + + public function saveStateAsync( + string $storeName, + string $key, + mixed $value, + ?Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface { + $item = new StateItem($key, $value, $consistency, null, $metadata); + return $this->handlePromise( + $this->httpClient->postAsync( + "/v1.0/state/$storeName", + [ + 'body' => $this->serializer->as_json([$item]) + ] + ) + ); + } + + public function trySaveState( + string $storeName, + string $key, + mixed $value, + string $etag, + ?Consistency $consistency = null, + array $metadata = [] + ): bool { + return $this->trySaveStateAsync($storeName, $key, $value, $etag, $consistency, $metadata)->wait(); + } + + public function trySaveStateAsync( + string $storeName, + string $key, + mixed $value, + string $etag, + ?Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface { + $item = new StateItem($key, $value, $consistency ?? new EventualFirstWrite(), $etag, $metadata); + return $this->handlePromise( + $this->httpClient->postAsync( + "/v1.0/state/$storeName", + [ + 'body' => $this->serializer->as_json([$item]) + ] + ), + fn(ResponseInterface $response) => true, + fn(\Throwable $exception) => false + ); + } + + public function getStateAndEtag( + string $storeName, + string $key, + string $asType = 'array', + ?Consistency $consistency = null, + array $metadata = [] + ): array { + return $this->getStateAndEtagAsync($storeName, $key, $asType, $consistency, $metadata)->wait(); + } + + public function executeStateTransaction(string $storeName, array $operations, array $metadata = []): void + { + $this->executeStateTransactionAsync($storeName, $operations, $metadata)->wait(); + } + + /** + * @param string $storeName + * @param StateTransactionRequest[] $operations + * @param array $metadata + * @return PromiseInterface + */ + public function executeStateTransactionAsync( + string $storeName, + array $operations, + array $metadata = [] + ): PromiseInterface { + $options = [ + 'body' => $this->serializer->as_json( + [ + 'operations' => array_map( + fn($operation) => [ + 'operation' => $operation->operationType, + 'request' => array_merge( + [ + 'key' => $operation->key, + 'value' => $operation->value, + ], + empty($operation->etag) ? [] : ['etag' => $operation->etag], + empty($operation->metadata) ? [] : ['metadata' => $operation->metadata], + empty($operation->consistency) ? [] : [ + 'options' => [ + 'consistency' => $operation->consistency->get_consistency(), + 'concurrency' => $operation->consistency->get_concurrency(), + ], + ], + ), + ], + $operations + ), + 'metadata' => $metadata, + ] + ), + ]; + return $this->handlePromise($this->httpClient->postAsync("/v1.0/state/$storeName/transaction", $options)); + } + + public function deleteState( + string $storeName, + string $key, + Consistency $consistency = null, + array $metadata = [] + ): void { + $this->deleteStateAsync($storeName, $key, $consistency, $metadata)->wait(); + } + + public function deleteStateAsync( + string $storeName, + string $key, + Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface { + return $this->tryDeleteStateAsync($storeName, $key, null, $consistency ?? new EventualLastWrite(), $metadata); + } + + public function tryDeleteStateAsync( + string $storeName, + string $key, + string $etag, + Consistency $consistency = null, + array $metadata = [] + ): PromiseInterface { + $consistency ??= new EventualFirstWrite(); + return $this->handlePromise( + $this->httpClient->deleteAsync( + "/v1.0/state/$storeName/$key", + array_merge( + [ + 'query' => empty($consistency) ? [] : [ + 'consistency' => $consistency->get_consistency(), + 'concurrency' => $consistency->get_concurrency(), + ], + ], + empty($etag) ? [] : [ + 'headers' => [ + 'If-Match' => $etag + ] + ] + ) + ), + fn(ResponseInterface $response) => true, + fn(\Throwable $error) => false + ); + } + + public function tryDeleteState( + string $storeName, + string $key, + string $etag, + Consistency $consistency = null, + array $metadata = [] + ): bool { + return $this->tryDeleteStateAsync($storeName, $key, $etag, $consistency, $metadata)->wait(); + } +} diff --git a/src/lib/Client/PromiseHandlingTrait.php b/src/lib/Client/PromiseHandlingTrait.php new file mode 100644 index 0000000..6b48d54 --- /dev/null +++ b/src/lib/Client/PromiseHandlingTrait.php @@ -0,0 +1,42 @@ + $response; + } + if (empty($errorTransformer)) { + $errorTransformer = fn(\Throwable $exception) => match ($exception::class) { + ServerException::class, ClientException::class => new DaprException( + $exception->hasResponse() + ? $exception->getResponse()->getBody()->getContents() + : $exception->getMessage(), + $exception->getCode(), + $exception + ), + default => $exception + }; + } + return $closure->then( + $transformResult, + $errorTransformer + ); + } +} diff --git a/src/lib/Client/StateTransactionRequest.php b/src/lib/Client/StateTransactionRequest.php new file mode 100644 index 0000000..76cb537 --- /dev/null +++ b/src/lib/Client/StateTransactionRequest.php @@ -0,0 +1,31 @@ + $metadata + * @param Consistency|null $consistency + */ + public function __construct( + public string $key, + public string $value, + public string $operationType, + public string $etag = '', + public array $metadata = [], + public Consistency|null $consistency = null + ) { + } +} From 288b63082211613491a659f996e3a4b4e5e6bc1e Mon Sep 17 00:00:00 2001 From: Rob Landers Date: Wed, 9 Jun 2021 23:03:49 +0200 Subject: [PATCH 2/4] Url encode string --- src/lib/Client/DaprHttpClient.php | 6 +++++- src/lib/Client/HttpSecretsTrait.php | 3 +++ src/lib/Client/HttpStateTrait.php | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lib/Client/DaprHttpClient.php b/src/lib/Client/DaprHttpClient.php index cab220d..32cecf1 100644 --- a/src/lib/Client/DaprHttpClient.php +++ b/src/lib/Client/DaprHttpClient.php @@ -51,7 +51,7 @@ public function invokeBindingAsync(BindingRequest $bindingRequest, string $dataT { return $this->handlePromise( $this->httpClient->putAsync( - '/v1.0/bindings/' . $bindingRequest->bindingName, + '/v1.0/bindings/' . rawurlencode($bindingRequest->bindingName), [ 'body' => $this->serializer->as_json( [ @@ -88,6 +88,8 @@ public function publishEventAsync( 'query' => $metadata, 'body' => $this->serializer->as_json($data) ]; + $pubsubName = rawurlencode($pubsubName); + $topicName = rawurlencode($topicName); return $this->handlePromise($this->httpClient->postAsync("/v1.0/publish/$pubsubName/$topicName", $options)); } @@ -118,6 +120,8 @@ public function invokeMethodAsync( $options['body'] = $this->serializer->as_json($data); } $options['headers'] = $metadata; + $appId = rawurlencode($appId); + $methodName = rawurlencode($methodName); return $this->handlePromise( $this->httpClient->requestAsync($httpMethod, "/v1.0/invoke/$appId/$methodName", $options) ); diff --git a/src/lib/Client/HttpSecretsTrait.php b/src/lib/Client/HttpSecretsTrait.php index 5d7f9e7..b38064d 100644 --- a/src/lib/Client/HttpSecretsTrait.php +++ b/src/lib/Client/HttpSecretsTrait.php @@ -27,6 +27,8 @@ public function getSecret(string $storeName, string $key, array $metadata = []): public function getSecretAsync(string $storeName, string $key, array $metadata = []): PromiseInterface { + $storeName = rawurlencode($storeName); + $key = rawurlencode($key); return $this->handlePromise( $this->httpClient->getAsync("/v1.0/secrets/$storeName/$key", ['query' => $metadata]), fn(ResponseInterface $response) => $this->deserializer->from_json( @@ -43,6 +45,7 @@ public function getBulkSecret(string $storeName, array $metadata = []): array public function getBulkSecretAsync(string $storeName, array $metadata = []): PromiseInterface { + $storeName = rawurlencode($storeName); return $this->handlePromise( $this->httpClient->getAsync( "/v1.0/secrets/$storeName/bulk", diff --git a/src/lib/Client/HttpStateTrait.php b/src/lib/Client/HttpStateTrait.php index 832b6d1..1742e70 100644 --- a/src/lib/Client/HttpStateTrait.php +++ b/src/lib/Client/HttpStateTrait.php @@ -60,6 +60,8 @@ public function getStateAndEtagAsync( $options['concurrency'] = $consistency->get_concurrency(); } $options = array_merge($options, $metadata); + $storeName = rawurlencode($storeName); + $key = rawurlencode($key); return $this->handlePromise( $this->httpClient->getAsync( "/v1.0/state/$storeName/$key", @@ -95,6 +97,7 @@ public function saveStateAsync( array $metadata = [] ): PromiseInterface { $item = new StateItem($key, $value, $consistency, null, $metadata); + $storeName = rawurlencode($storeName); return $this->handlePromise( $this->httpClient->postAsync( "/v1.0/state/$storeName", @@ -125,6 +128,7 @@ public function trySaveStateAsync( array $metadata = [] ): PromiseInterface { $item = new StateItem($key, $value, $consistency ?? new EventualFirstWrite(), $etag, $metadata); + $storeName = rawurlencode($storeName); return $this->handlePromise( $this->httpClient->postAsync( "/v1.0/state/$storeName", @@ -190,6 +194,7 @@ public function executeStateTransactionAsync( ] ), ]; + $storeName = rawurlencode($storeName); return $this->handlePromise($this->httpClient->postAsync("/v1.0/state/$storeName/transaction", $options)); } @@ -219,6 +224,8 @@ public function tryDeleteStateAsync( array $metadata = [] ): PromiseInterface { $consistency ??= new EventualFirstWrite(); + $storeName = rawurlencode($storeName); + $key = rawurlencode($key); return $this->handlePromise( $this->httpClient->deleteAsync( "/v1.0/state/$storeName/$key", From 2eba436a6c5627a44cb5b1bfd04ea18bfe3bb1e9 Mon Sep 17 00:00:00 2001 From: Rob Landers Date: Thu, 10 Jun 2021 23:25:10 +0200 Subject: [PATCH 3/4] Start upgrading the state manager --- composer.lock | 130 +++++++++++++++++++++++++-------- src/lib/State/StateManager.php | 69 ++++++++++++----- 2 files changed, 149 insertions(+), 50 deletions(-) diff --git a/composer.lock b/composer.lock index 319e916..78f4b9d 100644 --- a/composer.lock +++ b/composer.lock @@ -936,16 +936,16 @@ }, { "name": "php-di/php-di", - "version": "6.3.3", + "version": "6.3.4", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "da8e476cafc8011477e2ec9fd2e4706947758af2" + "reference": "f53bcba06ab31b18e911b77c039377f4ccd1f7a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/da8e476cafc8011477e2ec9fd2e4706947758af2", - "reference": "da8e476cafc8011477e2ec9fd2e4706947758af2", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/f53bcba06ab31b18e911b77c039377f4ccd1f7a5", + "reference": "f53bcba06ab31b18e911b77c039377f4ccd1f7a5", "shasum": "" }, "require": { @@ -996,7 +996,7 @@ ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", - "source": "https://github.com/PHP-DI/PHP-DI/tree/6.3.3" + "source": "https://github.com/PHP-DI/PHP-DI/tree/6.3.4" }, "funding": [ { @@ -1008,7 +1008,7 @@ "type": "tidelift" } ], - "time": "2021-05-01T16:26:47+00:00" + "time": "2021-06-10T08:04:48+00:00" }, { "name": "php-di/phpdoc-reader", @@ -2932,16 +2932,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.4", + "version": "9.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c73c6737305e779771147af66c96ca6a7ed8a741" + "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741", - "reference": "c73c6737305e779771147af66c96ca6a7ed8a741", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276", + "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276", "shasum": "" }, "require": { @@ -2971,7 +2971,7 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3", + "sebastian/type": "^2.3.2", "sebastian/version": "^3.0.2" }, "require-dev": { @@ -3019,7 +3019,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5" }, "funding": [ { @@ -3031,7 +3031,7 @@ "type": "github" } ], - "time": "2021-03-23T07:16:29+00:00" + "time": "2021-06-05T04:49:07+00:00" }, { "name": "sebastian/cli-parser", @@ -3890,16 +3890,16 @@ }, { "name": "sebastian/type", - "version": "2.3.1", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" + "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", - "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0d1c587401514d17e8f9258a27e23527cb1b06c1", + "reference": "0d1c587401514d17e8f9258a27e23527cb1b06c1", "shasum": "" }, "require": { @@ -3934,7 +3934,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.1" + "source": "https://github.com/sebastianbergmann/type/tree/2.3.2" }, "funding": [ { @@ -3942,7 +3942,7 @@ "type": "github" } ], - "time": "2020-10-26T13:18:59+00:00" + "time": "2021-06-04T13:02:07+00:00" }, { "name": "sebastian/version", @@ -3999,20 +3999,21 @@ }, { "name": "symfony/console", - "version": "v5.2.8", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" + "reference": "058553870f7809087fa80fa734704a21b9bcaeb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", - "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", + "url": "https://api.github.com/repos/symfony/console/zipball/058553870f7809087fa80fa734704a21b9bcaeb2", + "reference": "058553870f7809087fa80fa734704a21b9bcaeb2", "shasum": "" }, "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", "symfony/polyfill-php80": "^1.15", @@ -4076,7 +4077,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.8" + "source": "https://github.com/symfony/console/tree/v5.3.0" }, "funding": [ { @@ -4092,7 +4093,74 @@ "type": "tidelift" } ], - "time": "2021-05-11T15:45:21+00:00" + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4661,16 +4729,16 @@ }, { "name": "symfony/string", - "version": "v5.2.8", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" + "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", - "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "url": "https://api.github.com/repos/symfony/string/zipball/a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", + "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", "shasum": "" }, "require": { @@ -4724,7 +4792,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.8" + "source": "https://github.com/symfony/string/tree/v5.3.0" }, "funding": [ { @@ -4740,7 +4808,7 @@ "type": "tidelift" } ], - "time": "2021-05-10T14:56:10+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "theseer/tokenizer", diff --git a/src/lib/State/StateManager.php b/src/lib/State/StateManager.php index 6f2ea4b..5e4f85a 100644 --- a/src/lib/State/StateManager.php +++ b/src/lib/State/StateManager.php @@ -27,12 +27,16 @@ class StateManager implements IManageState protected static WeakMap $obj_meta; public function __construct( - protected LoggerInterface $logger, - protected ISerializer $serializer, - protected IDeserializer $deserializer, - protected DaprClient $client + protected LoggerInterface|null $logger = null, + protected ISerializer|null $serializer = null, + protected IDeserializer|null $deserializer = null, + protected DaprClient|\Dapr\Client\DaprClient|null $client = null ) { - if ( ! isset(self::$obj_meta)) { + if ($client instanceof \Dapr\Client\DaprClient && ($logger !== null || $serializer !== null || $deserializer !== null)) { + throw new \LogicException('All parameters must be null when using the new client!'); + } + + if (!isset(self::$obj_meta)) { self::$obj_meta = new WeakMap(); } } @@ -45,6 +49,10 @@ public function save_state( string $store_name, StateItem $item ): void { + if ($this->client instanceof \Dapr\Client\DaprClient) { + $this->client->saveState($store_name, $item->key, $item->value, $item->consistency, $item->metadata); + return; + } $request = [ $this->serializer->as_array($item), ]; @@ -60,8 +68,19 @@ public function load_state( string $key, mixed $default_value = null, array $metadata = [], - ?Consistency $consistency = null + ?Consistency $consistency = null, + string $as_type = 'mixed' ): StateItem { + if ($this->client instanceof \Dapr\Client\DaprClient) { + ['etag' => $etag, 'value' => $value] = $this->client->getStateAndEtag( + $store_name, + $key, + $as_type, + $consistency, + $metadata + ); + return new StateItem($key, $value ?? $default_value, $consistency, $etag, $metadata); + } $data = $this->client->get("/state/$store_name/$key", $metadata); switch ($data->code) { case KeyResponse::KEY_NOT_FOUND: @@ -74,6 +93,10 @@ public function load_state( public function delete_keys(string $store_name, array $keys, array $metadata = []): void { + if ($this->client instanceof \Dapr\Client\DaprClient) { + throw new \LogicException('not implemented'); + } + foreach ($keys as $key) { $this->client->delete("/state/$store_name/$key", $metadata); } @@ -91,18 +114,18 @@ public function save_object( ): void { $this->logger->debug('Saving state'); $reflection = new ReflectionClass($item); - $store = self::get_description($reflection); - $keys = self::$obj_meta[$item] ?? []; - $request = []; + $store = self::get_description($reflection); + $keys = self::$obj_meta[$item] ?? []; + $request = []; foreach ($reflection->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { - $key = $prefix.$property->getName(); + $key = $prefix . $property->getName(); $value = [ - 'key' => $key, + 'key' => $key, 'value' => $this->serializer->as_array($item->{$property->getName()} ?? null), ]; if (isset($keys[$key]['etag'])) { - $value['etag'] = $keys[$key]['etag']; + $value['etag'] = $keys[$key]['etag']; $value['options'] = [ 'consistency' => ($consistency ?? new EventualLastWrite())->get_consistency(), 'concurrency' => ($consistency ?? new EventualLastWrite())->get_concurrency(), @@ -114,6 +137,10 @@ public function save_object( $request[] = $value; } + if ($this->client instanceof \Dapr\Client\DaprClient) { + throw new \LogicException('Not implemented'); + } + $this->client->post("/state/{$store->name}", $request); } @@ -123,16 +150,20 @@ public function save_object( */ public function load_object(object $into, string $prefix = '', int $parallelism = 10, array $metadata = []): void { + if ($this->client instanceof \Dapr\Client\DaprClient) { + throw new \LogicException('Not implemented'); + } + $this->logger->debug('Loading state'); $reflection = new ReflectionClass($into); $store_name = self::get_description($reflection)->name; - $keys = []; + $keys = []; $properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC); - $result = $this->client->post( + $result = $this->client->post( "/state/$store_name/bulk", [ - 'keys' => array_map( - fn($key) => $prefix.$key, + 'keys' => array_map( + fn($key) => $prefix . $key, array_column($properties, 'name') ), 'parallelism' => $parallelism, @@ -140,7 +171,7 @@ public function load_object(object $into, string $prefix = '', int $parallelism $metadata ); foreach ($result->data as $value) { - $key = $value['key']; + $key = $value['key']; $prop_name = empty($prefix) ? $key : substr($key, strlen($prefix)); if (isset($value['data'])) { $value['data'] = $this->deserializer->detect_from_property( @@ -149,10 +180,10 @@ public function load_object(object $into, string $prefix = '', int $parallelism ); } if (isset($value['data']) && $value['data'] !== null) { - $into->$prop_name = $value['data']; + $into->$prop_name = $value['data']; $keys[$key]['etag'] = $value['etag']; } elseif (isset($value['etag'])) { - $into->$prop_name = null; + $into->$prop_name = null; $keys[$key]['etag'] = $value['etag']; } } From 939636ba3b4d039d25ef0440b7d4f2d92bc4954e Mon Sep 17 00:00:00 2001 From: Rob Landers Date: Fri, 25 Jun 2021 15:16:09 +0200 Subject: [PATCH 4/4] Don't url encode method name --- src/lib/Client/DaprHttpClient.php | 1 - src/lib/Client/PromiseHandlingTrait.php | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/Client/DaprHttpClient.php b/src/lib/Client/DaprHttpClient.php index 32cecf1..a19badb 100644 --- a/src/lib/Client/DaprHttpClient.php +++ b/src/lib/Client/DaprHttpClient.php @@ -121,7 +121,6 @@ public function invokeMethodAsync( } $options['headers'] = $metadata; $appId = rawurlencode($appId); - $methodName = rawurlencode($methodName); return $this->handlePromise( $this->httpClient->requestAsync($httpMethod, "/v1.0/invoke/$appId/$methodName", $options) ); diff --git a/src/lib/Client/PromiseHandlingTrait.php b/src/lib/Client/PromiseHandlingTrait.php index 6b48d54..352adc7 100644 --- a/src/lib/Client/PromiseHandlingTrait.php +++ b/src/lib/Client/PromiseHandlingTrait.php @@ -20,7 +20,9 @@ private function handlePromise( callable|null $errorTransformer = null ): PromiseInterface { if (empty($transformResult)) { - $transformResult = fn(ResponseInterface $response) => $response; + $transformResult = fn( + ResponseInterface|DaprException $response + ) => $response instanceof DaprException ? throw $response : $response; } if (empty($errorTransformer)) { $errorTransformer = fn(\Throwable $exception) => match ($exception::class) {