From d6b548c535cc3bd9bec06835d795939d2c5bf442 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Sun, 25 Oct 2015 22:53:34 +0100 Subject: [PATCH 01/10] Replace sendRequests with an async approach --- src/HttpAsyncClient.php | 24 ++++++++++++++++++++++++ src/HttpClient.php | 1 - src/Promise.php | 22 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/HttpAsyncClient.php create mode 100644 src/Promise.php diff --git a/src/HttpAsyncClient.php b/src/HttpAsyncClient.php new file mode 100644 index 0000000..737ee63 --- /dev/null +++ b/src/HttpAsyncClient.php @@ -0,0 +1,24 @@ + + */ +interface HttpAsyncClient +{ + /** + * Sends a PSR-7 request in an asynchronous way. + * + * @param RequestInterface $request + * + * @return Promise + * + * @throws Exception + */ + public function sendAsyncRequest(RequestInterface $request); +} diff --git a/src/HttpClient.php b/src/HttpClient.php index 525f9e0..fa66c2c 100644 --- a/src/HttpClient.php +++ b/src/HttpClient.php @@ -2,7 +2,6 @@ namespace Http\Client; -use Http\Client\Exception\BatchException; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; diff --git a/src/Promise.php b/src/Promise.php new file mode 100644 index 0000000..5b1ad74 --- /dev/null +++ b/src/Promise.php @@ -0,0 +1,22 @@ + + */ +interface Promise +{ + /** + * Add behavior for when the promise is resolved or rejected (response will be available, or error happens) + * + * @param callable $onFulfilled Called when a response will be available, it will receive a Psr\Http\Message\RequestInterface object as the first argument + * @param callable $onRejected Called when an error happens, it will receive a Http\Client\Exception object as the first argument + * + * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected) + */ + public function then(callable $onFulfilled = null, callable $onRejected = null); +} From 9b7bbf2ea07e949f44db0440ec11724c4f86ae8d Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 26 Oct 2015 00:05:29 +0100 Subject: [PATCH 02/10] Force callback to be set --- src/Promise.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Promise.php b/src/Promise.php index 5b1ad74..c7e7f7a 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -18,5 +18,5 @@ interface Promise * * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected) */ - public function then(callable $onFulfilled = null, callable $onRejected = null); + public function then(callable $onFulfilled, callable $onRejected); } From b6c54344d13fe95823afc024c1dd19f4bb388674 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 26 Oct 2015 14:55:36 +0100 Subject: [PATCH 03/10] Use specification of promises/a+ --- src/Promise.php | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Promise.php b/src/Promise.php index c7e7f7a..cb924ea 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -10,13 +10,31 @@ */ interface Promise { + const PENDING = 0; + const FULFILLED = 1; + const REJECTED = 2; + /** * Add behavior for when the promise is resolved or rejected (response will be available, or error happens) * - * @param callable $onFulfilled Called when a response will be available, it will receive a Psr\Http\Message\RequestInterface object as the first argument - * @param callable $onRejected Called when an error happens, it will receive a Http\Client\Exception object as the first argument + * @param callable $onFulfilled Called when a response will be available. + * + * It will receive a Psr\Http\Message\RequestInterface object as the first argument + * If the callback is null it should not be called. + * + * @param callable $onRejected Called when an error happens. + * + * It will receive a Http\Client\Exception object as the first argument. + * If the callback is null it should not be called. * * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected) */ - public function then(callable $onFulfilled, callable $onRejected); + public function then(callable $onFulfilled = null, callable $onRejected = null); + + /** + * Get the state of the promise, one of PENDING, FULFILLED or REJECTED + * + * @return int + */ + public function getState(); } From 5628eee8510535e3fe55ac7de9d416643fa333d8 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 26 Oct 2015 15:03:46 +0100 Subject: [PATCH 04/10] Replace "should" by "must" --- src/Promise.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Promise.php b/src/Promise.php index cb924ea..59f1512 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -20,12 +20,12 @@ interface Promise * @param callable $onFulfilled Called when a response will be available. * * It will receive a Psr\Http\Message\RequestInterface object as the first argument - * If the callback is null it should not be called. + * If the callback is null it must not be called. * * @param callable $onRejected Called when an error happens. * * It will receive a Http\Client\Exception object as the first argument. - * If the callback is null it should not be called. + * If the callback is null it must not be called. * * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected) */ From 1c569e7de504c4f1cb869675294bc2108f4a7380 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 26 Oct 2015 18:12:56 +0100 Subject: [PATCH 05/10] Add documentation about states, add method to get value and reason of the promise --- src/Promise.php | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Promise.php b/src/Promise.php index 59f1512..c3073fe 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -2,6 +2,8 @@ namespace Http\Client; +use Psr\Http\Message\ResponseInterface; + /** * Promise represents a response that may not be available yet, but will be resolved at some point in future. * It acts like a proxy to the actual response. @@ -10,8 +12,27 @@ */ interface Promise { + /** + * Pending state, promise has not been fulfilled or rejected. + * + * When pending, a promise may transition to either the fulfilled or rejected state. + */ const PENDING = 0; + + /** + * Fulfilled state, promise has been fulfilled with a ResponseInterface object. + * + * When fulfilled, a promise must not transition to any other state. + * When fulfilled, a promise must have a value, which must not change. + */ const FULFILLED = 1; + + /** + * Rejected state, promise has been rejected with an Exception object. + * + * When rejected, a promise must not transition to any other state. + * When rejected, a promise must have a reason, which must not change. + */ const REJECTED = 2; /** @@ -21,11 +42,17 @@ interface Promise * * It will receive a Psr\Http\Message\RequestInterface object as the first argument * If the callback is null it must not be called. + * It must be called after promise is fulfilled, with promise’s value (ResponseInterface) as its first argument. + * It must not be called before promise is fulfilled. + * It must not be called more than once. * - * @param callable $onRejected Called when an error happens. + * @param callable $onRejected Called when an error happens. * * It will receive a Http\Client\Exception object as the first argument. * If the callback is null it must not be called. + * It must be called after promise is rejected, with promise’s reason (Exception) as its first argument. + * It must not be called before promise is rejected. + * It must not be called more than once. * * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected) */ @@ -37,4 +64,18 @@ public function then(callable $onFulfilled = null, callable $onRejected = null); * @return int */ public function getState(); + + /** + * Return the value of the promise (fulfilled) + * + * @return null|ResponseInterface Null if the promise is rejected or pending, the response object otherwise + */ + public function getResponse(); + + /** + * Return the reason of the promise (rejected) + * + * @return null|Exception Null if the promise is fulfilled or pending, the exception object otherwise + */ + public function getError(); } From 5a868bdd98a9cf86f10844c4b6b571a305ed8155 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 26 Oct 2015 18:16:30 +0100 Subject: [PATCH 06/10] Add note about promises/a+ --- src/Promise.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Promise.php b/src/Promise.php index c3073fe..7d20d20 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -8,6 +8,10 @@ * Promise represents a response that may not be available yet, but will be resolved at some point in future. * It acts like a proxy to the actual response. * + * This interface is an extension of the promises/a+ specification https://promisesaplus.com/ + * Value is replaced by an object where its class implement a Psr\Http\Message\RequestInterface. + * Reason is replaced by an object where its class implement a Http\Client\Exception. + * * @author Joel Wurtz */ interface Promise From 21e01c130e7f7963d18ce0b567e3a053d8bbcd97 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 26 Oct 2015 18:18:10 +0100 Subject: [PATCH 07/10] Fix typo on request <-> response --- src/Promise.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Promise.php b/src/Promise.php index 7d20d20..553fc1a 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -44,7 +44,7 @@ interface Promise * * @param callable $onFulfilled Called when a response will be available. * - * It will receive a Psr\Http\Message\RequestInterface object as the first argument + * It will receive a Psr\Http\Message\ResponseInterface object as the first argument * If the callback is null it must not be called. * It must be called after promise is fulfilled, with promise’s value (ResponseInterface) as its first argument. * It must not be called before promise is fulfilled. From f2af5cb52851cd41342db443896bcf59bea68e08 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Thu, 29 Oct 2015 21:16:35 +0100 Subject: [PATCH 08/10] Fix documentation from an user point of view --- src/Promise.php | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/src/Promise.php b/src/Promise.php index 553fc1a..31a9c80 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -18,47 +18,29 @@ interface Promise { /** * Pending state, promise has not been fulfilled or rejected. - * - * When pending, a promise may transition to either the fulfilled or rejected state. */ const PENDING = 0; /** * Fulfilled state, promise has been fulfilled with a ResponseInterface object. - * - * When fulfilled, a promise must not transition to any other state. - * When fulfilled, a promise must have a value, which must not change. */ const FULFILLED = 1; /** * Rejected state, promise has been rejected with an Exception object. - * - * When rejected, a promise must not transition to any other state. - * When rejected, a promise must have a reason, which must not change. */ const REJECTED = 2; /** - * Add behavior for when the promise is resolved or rejected (response will be available, or error happens) + * Add behavior for when the promise is resolved or rejected (response will be available, or error happens). * * @param callable $onFulfilled Called when a response will be available. - * - * It will receive a Psr\Http\Message\ResponseInterface object as the first argument - * If the callback is null it must not be called. - * It must be called after promise is fulfilled, with promise’s value (ResponseInterface) as its first argument. - * It must not be called before promise is fulfilled. - * It must not be called more than once. - * * @param callable $onRejected Called when an error happens. * - * It will receive a Http\Client\Exception object as the first argument. - * If the callback is null it must not be called. - * It must be called after promise is rejected, with promise’s reason (Exception) as its first argument. - * It must not be called before promise is rejected. - * It must not be called more than once. + * If you do not care about one of the cases, you can set the corresponding callable to null + * The callback will be called when the response or exception arrived and never more than once. * - * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected) + * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected). */ public function then(callable $onFulfilled = null, callable $onRejected = null); @@ -70,16 +52,20 @@ public function then(callable $onFulfilled = null, callable $onRejected = null); public function getState(); /** - * Return the value of the promise (fulfilled) + * Return the value of the promise (fulfilled). + * + * @throws \LogicException When the promise is not fulfilled. * - * @return null|ResponseInterface Null if the promise is rejected or pending, the response object otherwise + * @return ResponseInterface Response Object only when the Promise is fulfilled. */ public function getResponse(); /** - * Return the reason of the promise (rejected) + * Return the reason of the promise (rejected). + * + * @throws \LogicException When the promise is not rejected. * - * @return null|Exception Null if the promise is fulfilled or pending, the exception object otherwise + * @return Exception Exception Object only when the Promise is rejected. */ public function getError(); } From fe7d30b65c42a47a29b3e5ecccbe81b57911c5b3 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Sat, 31 Oct 2015 01:22:47 +0100 Subject: [PATCH 09/10] Use string for constant, add wait method, add some documentation about callback --- src/Promise.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Promise.php b/src/Promise.php index 31a9c80..acef6e0 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -19,26 +19,28 @@ interface Promise /** * Pending state, promise has not been fulfilled or rejected. */ - const PENDING = 0; + const PENDING = "pending"; /** * Fulfilled state, promise has been fulfilled with a ResponseInterface object. */ - const FULFILLED = 1; + const FULFILLED = "fulfilled"; /** * Rejected state, promise has been rejected with an Exception object. */ - const REJECTED = 2; + const REJECTED = "rejected"; /** * Add behavior for when the promise is resolved or rejected (response will be available, or error happens). * + * If you do not care about one of the cases, you can set the corresponding callable to null + * The callback will be called when the response or exception arrived and never more than once. + * * @param callable $onFulfilled Called when a response will be available. * @param callable $onRejected Called when an error happens. * - * If you do not care about one of the cases, you can set the corresponding callable to null - * The callback will be called when the response or exception arrived and never more than once. + * You must always return the Response in the interface or throw an Exception. * * @return Promise Always returns a new promise which is resolved with value of the executed callback (onFulfilled / onRejected). */ @@ -68,4 +70,13 @@ public function getResponse(); * @return Exception Exception Object only when the Promise is rejected. */ public function getError(); + + /** + * Wait for the promise to be fulfilled or rejected. + * + * This function does not return a result, it simply wait for response or error + * of the request to be available, change the state of the promise and call one + * of the then callable. + */ + public function wait(); } From 55b159fe639e627d0824f13fde536009f4ad440f Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Wed, 4 Nov 2015 10:47:52 +0100 Subject: [PATCH 10/10] Fixing phpdoc, rename getError to getException --- src/Promise.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Promise.php b/src/Promise.php index acef6e0..575bc6e 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -38,7 +38,7 @@ interface Promise * The callback will be called when the response or exception arrived and never more than once. * * @param callable $onFulfilled Called when a response will be available. - * @param callable $onRejected Called when an error happens. + * @param callable $onRejected Called when an error happens. * * You must always return the Response in the interface or throw an Exception. * @@ -56,27 +56,28 @@ public function getState(); /** * Return the value of the promise (fulfilled). * - * @throws \LogicException When the promise is not fulfilled. - * * @return ResponseInterface Response Object only when the Promise is fulfilled. + * + * @throws \LogicException When the promise is not fulfilled. */ public function getResponse(); /** * Return the reason of the promise (rejected). * - * @throws \LogicException When the promise is not rejected. - * * @return Exception Exception Object only when the Promise is rejected. + * + * If the exception is an instance of Http\Client\Exception\HttpException it will contain + * the response object with the status code and the http reason. + * + * @throws \LogicException When the promise is not rejected. */ - public function getError(); + public function getException(); /** * Wait for the promise to be fulfilled or rejected. * - * This function does not return a result, it simply wait for response or error - * of the request to be available, change the state of the promise and call one - * of the then callable. + * When this method returns, the request has been resolved and the appropriate callable has terminated. */ public function wait(); }