Skip to content

Commit 92328c5

Browse files
committed
Merge pull request #1 from php-http/tools
Add client decorators and emulators
2 parents 87c3bcd + 79aa62d commit 92328c5

11 files changed

+338
-3
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"require": {
1414
"php": ">=5.4",
1515
"php-http/httplug": "1.0.0-beta",
16-
"php-http/message-factory": "^1.0"
16+
"php-http/message-factory": "^1.0",
17+
"php-http/promise": "^0.1.1"
1718
},
1819
"require-dev": {
1920
"phpspec/phpspec": "^2.4",

spec/BatchClientSpec.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
namespace spec\Http\Client\Common;
44

55
use Http\Client\HttpClient;
6-
use PhpSpec\ObjectBehavior;
76
use Psr\Http\Message\RequestInterface;
87
use Psr\Http\Message\ResponseInterface;
8+
use PhpSpec\ObjectBehavior;
99

1010
class BatchClientSpec extends ObjectBehavior
1111
{

spec/HttpAsyncClientDecoratorSpec.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace spec\Http\Client\Common;
4+
5+
use Http\Client\HttpAsyncClient;
6+
use Http\Client\Common\HttpAsyncClientDecorator;
7+
use Http\Promise\Promise;
8+
use Psr\Http\Message\RequestInterface;
9+
use PhpSpec\ObjectBehavior;
10+
11+
class HttpAsyncClientDecoratorSpec extends ObjectBehavior
12+
{
13+
function let(HttpAsyncClient $httpAsyncClient)
14+
{
15+
$this->beAnInstanceOf('spec\Http\Client\Common\HttpAsyncClientDecoratorStub', [$httpAsyncClient]);
16+
}
17+
18+
function it_is_initializable()
19+
{
20+
$this->shouldHaveType('spec\Http\Client\Common\HttpAsyncClientDecoratorStub');
21+
}
22+
23+
function it_is_an_http_async_client()
24+
{
25+
$this->shouldImplement('Http\Client\HttpAsyncClient');
26+
}
27+
28+
function it_decorates_the_underlying_client(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise)
29+
{
30+
$httpAsyncClient->sendAsyncRequest($request)->willReturn($promise);
31+
32+
$this->sendAsyncRequest($request)->shouldReturn($promise);
33+
}
34+
}
35+
36+
class HttpAsyncClientDecoratorStub implements HttpAsyncClient
37+
{
38+
use HttpAsyncClientDecorator;
39+
40+
/**
41+
* @param HttpAsyncClient $httpAsyncClient
42+
*/
43+
public function __construct(HttpAsyncClient $httpAsyncClient)
44+
{
45+
$this->httpAsyncClient = $httpAsyncClient;
46+
}
47+
}

spec/HttpAsyncClientEmulatorSpec.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace spec\Http\Client\Common;
4+
5+
use Http\Client\HttpAsyncClient;
6+
use Http\Client\HttpClient;
7+
use Http\Client\Common\HttpAsyncClientEmulator;
8+
use Http\Client\Common\HttpClientDecorator;
9+
use Psr\Http\Message\RequestInterface;
10+
use Psr\Http\Message\ResponseInterface;
11+
use PhpSpec\ObjectBehavior;
12+
13+
class HttpAsyncClientEmulatorSpec extends ObjectBehavior
14+
{
15+
function let(HttpClient $httpClient)
16+
{
17+
$this->beAnInstanceOf('spec\Http\Client\Common\HttpAsyncClientEmulatorStub', [$httpClient]);
18+
}
19+
20+
function it_is_initializable()
21+
{
22+
$this->shouldHaveType('spec\Http\Client\Common\HttpAsyncClientEmulatorStub');
23+
}
24+
25+
function it_emulates_a_successful_request(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response)
26+
{
27+
$httpClient->sendRequest($request)->willReturn($response);
28+
29+
$this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Promise\FulfilledPromise');
30+
}
31+
32+
function it_emulates_a_failed_request(HttpClient $httpClient, RequestInterface $request)
33+
{
34+
$httpClient->sendRequest($request)->willThrow('Http\Client\Exception\TransferException');
35+
36+
$this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Promise\RejectedPromise');
37+
}
38+
}
39+
40+
class HttpAsyncClientEmulatorStub implements HttpClient, HttpAsyncClient
41+
{
42+
use HttpClientDecorator;
43+
use HttpAsyncClientEmulator;
44+
45+
/**
46+
* @param HttpClient $httpClient
47+
*/
48+
public function __construct(HttpClient $httpClient)
49+
{
50+
$this->httpClient = $httpClient;
51+
}
52+
}

spec/HttpClientDecoratorSpec.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace spec\Http\Client\Common;
4+
5+
use Http\Client\HttpClient;
6+
use Http\Client\Common\HttpClientDecorator;
7+
use Psr\Http\Message\RequestInterface;
8+
use Psr\Http\Message\ResponseInterface;
9+
use PhpSpec\ObjectBehavior;
10+
11+
class HttpClientDecoratorSpec extends ObjectBehavior
12+
{
13+
function let(HttpClient $httpClient)
14+
{
15+
$this->beAnInstanceOf('spec\Http\Client\Common\HttpClientDecoratorStub', [$httpClient]);
16+
}
17+
18+
function it_is_initializable()
19+
{
20+
$this->shouldHaveType('spec\Http\Client\Common\HttpClientDecoratorStub');
21+
}
22+
23+
function it_is_an_http_client()
24+
{
25+
$this->shouldImplement('Http\Client\HttpClient');
26+
}
27+
28+
function it_decorates_the_underlying_client(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response)
29+
{
30+
$httpClient->sendRequest($request)->willReturn($response);
31+
32+
$this->sendRequest($request)->shouldReturn($response);
33+
}
34+
}
35+
36+
class HttpClientDecoratorStub implements HttpClient
37+
{
38+
use HttpClientDecorator;
39+
40+
/**
41+
* @param HttpClient $httpClient
42+
*/
43+
public function __construct(HttpClient $httpClient)
44+
{
45+
$this->httpClient = $httpClient;
46+
}
47+
}

spec/HttpClientEmulatorSpec.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace spec\Http\Client\Common;
4+
5+
use Http\Client\Exception\TransferException;
6+
use Http\Client\HttpClient;
7+
use Http\Client\HttpAsyncClient;
8+
use Http\Client\Common\HttpClientEmulator;
9+
use Http\Client\Common\HttpAsyncClientDecorator;
10+
use Http\Promise\Promise;
11+
use Psr\Http\Message\RequestInterface;
12+
use Psr\Http\Message\ResponseInterface;
13+
use PhpSpec\ObjectBehavior;
14+
15+
class HttpClientEmulatorSpec extends ObjectBehavior
16+
{
17+
function let(HttpAsyncClient $httpAsyncClient)
18+
{
19+
$this->beAnInstanceOf('spec\Http\Client\Common\HttpClientEmulatorStub', [$httpAsyncClient]);
20+
}
21+
22+
function it_is_initializable()
23+
{
24+
$this->shouldHaveType('spec\Http\Client\Common\HttpClientEmulatorStub');
25+
}
26+
27+
function it_emulates_a_successful_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise, ResponseInterface $response)
28+
{
29+
$promise->wait()->shouldBeCalled();
30+
$promise->getState()->willReturn(Promise::FULFILLED);
31+
$promise->wait()->willReturn($response);
32+
33+
$httpAsyncClient->sendAsyncRequest($request)->willReturn($promise);
34+
35+
$this->sendRequest($request)->shouldReturn($response);
36+
}
37+
38+
function it_emulates_a_failed_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise)
39+
{
40+
$promise->wait()->shouldBeCalled();
41+
$promise->getState()->willReturn(Promise::REJECTED);
42+
$promise->wait()->willThrow(new TransferException());
43+
44+
$httpAsyncClient->sendAsyncRequest($request)->willReturn($promise);
45+
46+
$this->shouldThrow('Http\Client\Exception')->duringSendRequest($request);
47+
}
48+
}
49+
50+
class HttpClientEmulatorStub implements HttpAsyncClient, HttpClient
51+
{
52+
use HttpAsyncClientDecorator;
53+
use HttpClientEmulator;
54+
55+
/**
56+
* @param HttpAsyncClient $httpAsyncClient
57+
*/
58+
public function __construct(HttpAsyncClient $httpAsyncClient)
59+
{
60+
$this->httpAsyncClient = $httpAsyncClient;
61+
}
62+
}

spec/HttpMethodsClientSpec.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
use Http\Client\HttpClient;
77
use Http\Client\Common\HttpMethodsClient;
88
use Http\Message\MessageFactory;
9-
use PhpSpec\ObjectBehavior;
109
use Psr\Http\Message\RequestInterface;
1110
use Psr\Http\Message\ResponseInterface;
11+
use PhpSpec\ObjectBehavior;
1212

1313
class HttpMethodsClientSpec extends ObjectBehavior
1414
{

src/HttpAsyncClientDecorator.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Http\Client\Common;
4+
5+
use Http\Client\HttpAsyncClient;
6+
use Psr\Http\Message\RequestInterface;
7+
8+
/**
9+
* Decorates an HTTP Async Client.
10+
*
11+
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
12+
*/
13+
trait HttpAsyncClientDecorator
14+
{
15+
/**
16+
* @var HttpAsyncClient
17+
*/
18+
protected $httpAsyncClient;
19+
20+
/**
21+
* {@inheritdoc}
22+
*
23+
* @see HttpAsyncClient::sendAsyncRequest
24+
*/
25+
public function sendAsyncRequest(RequestInterface $request)
26+
{
27+
return $this->httpAsyncClient->sendAsyncRequest($request);
28+
}
29+
}

src/HttpAsyncClientEmulator.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Http\Client\Common;
4+
5+
use Http\Client\Exception;
6+
use Http\Promise;
7+
use Psr\Http\Message\RequestInterface;
8+
9+
/**
10+
* Emulates an HTTP Async Client in an HTTP Client.
11+
*
12+
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
13+
*/
14+
trait HttpAsyncClientEmulator
15+
{
16+
/**
17+
* {@inheritdoc}
18+
*
19+
* @see HttpClient::sendRequest
20+
*/
21+
abstract public function sendRequest(RequestInterface $request);
22+
23+
/**
24+
* {@inheritdoc}
25+
*
26+
* @see HttpAsyncClient::sendAsyncRequest
27+
*/
28+
public function sendAsyncRequest(RequestInterface $request)
29+
{
30+
try {
31+
return new Promise\FulfilledPromise($this->sendRequest($request));
32+
} catch (Exception $e) {
33+
return new Promise\RejectedPromise($e);
34+
}
35+
}
36+
}

src/HttpClientDecorator.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Http\Client\Common;
4+
5+
use Http\Client\HttpClient;
6+
use Psr\Http\Message\RequestInterface;
7+
8+
/**
9+
* Decorates an HTTP Client.
10+
*
11+
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
12+
*/
13+
trait HttpClientDecorator
14+
{
15+
/**
16+
* @var HttpClient
17+
*/
18+
protected $httpClient;
19+
20+
/**
21+
* {@inheritdoc}
22+
*
23+
* @see HttpClient::sendRequest
24+
*/
25+
public function sendRequest(RequestInterface $request)
26+
{
27+
return $this->httpClient->sendRequest($request);
28+
}
29+
}

src/HttpClientEmulator.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Http\Client\Common;
4+
5+
use Psr\Http\Message\RequestInterface;
6+
7+
/**
8+
* Emulates an HTTP Client in an HTTP Async Client.
9+
*
10+
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
11+
*/
12+
trait HttpClientEmulator
13+
{
14+
/**
15+
* {@inheritdoc}
16+
*
17+
* @see HttpClient::sendRequest
18+
*/
19+
public function sendRequest(RequestInterface $request)
20+
{
21+
$promise = $this->sendAsyncRequest($request);
22+
23+
return $promise->wait();
24+
}
25+
26+
/**
27+
* {@inheritdoc}
28+
*
29+
* @see HttpAsyncClient::sendAsyncRequest
30+
*/
31+
abstract public function sendAsyncRequest(RequestInterface $request);
32+
}

0 commit comments

Comments
 (0)