Skip to content

Commit c05df7b

Browse files
committed
Add http client router
1 parent c245496 commit c05df7b

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

spec/HttpClientRouterSpec.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace spec\Http\Client\Common;
4+
5+
use Http\Client\Common\RequestMatcher;
6+
use Http\Client\HttpAsyncClient;
7+
use Http\Client\HttpClient;
8+
use Http\Promise\Promise;
9+
use PhpSpec\ObjectBehavior;
10+
use Psr\Http\Message\RequestInterface;
11+
use Psr\Http\Message\ResponseInterface;
12+
13+
class HttpClientRouterSpec extends ObjectBehavior
14+
{
15+
function it_is_initializable()
16+
{
17+
$this->shouldHaveType('Http\Client\Common\HttpClientRouter');
18+
}
19+
20+
function it_is_an_http_client()
21+
{
22+
$this->shouldImplement('Http\Client\HttpClient');
23+
}
24+
25+
function it_is_an_async_http_client()
26+
{
27+
$this->shouldImplement('Http\Client\HttpAsyncClient');
28+
}
29+
30+
function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request, ResponseInterface $response)
31+
{
32+
$this->addClient($client, $matcher);
33+
$matcher->matches($request)->willReturn(true);
34+
$client->sendRequest($request)->willReturn($response);
35+
36+
$this->sendRequest($request)->shouldReturn($response);
37+
}
38+
39+
function it_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request, Promise $promise)
40+
{
41+
$this->addClient($client, $matcher);
42+
$matcher->matches($request)->willReturn(true);
43+
$client->sendAsyncRequest($request)->willReturn($promise);
44+
45+
$this->sendAsyncRequest($request)->shouldReturn($promise);
46+
}
47+
48+
function it_throw_exception_on_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request)
49+
{
50+
$this->addClient($client, $matcher);
51+
$matcher->matches($request)->willReturn(false);
52+
53+
$this->shouldThrow('Http\Client\Exception\RequestException')->duringSendRequest($request);
54+
}
55+
56+
function it_throw_exception_on_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request)
57+
{
58+
$this->addClient($client, $matcher);
59+
$matcher->matches($request)->willReturn(false);
60+
61+
$this->shouldThrow('Http\Client\Exception\RequestException')->duringSendAsyncRequest($request);
62+
}
63+
}

src/HttpClientRouter.php

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace Http\Client\Common;
4+
5+
use Http\Client\Exception\RequestException;
6+
use Http\Client\HttpAsyncClient;
7+
use Http\Client\HttpClient;
8+
use Psr\Http\Message\RequestInterface;
9+
10+
/**
11+
*
12+
*/
13+
class HttpClientRouter implements HttpClient, HttpAsyncClient
14+
{
15+
private $clients = [];
16+
17+
/**
18+
* {@inheritdoc}
19+
*/
20+
public function sendAsyncRequest(RequestInterface $request)
21+
{
22+
$client = $this->chooseHttpClient($request);
23+
24+
return $client->sendAsyncRequest($request);
25+
}
26+
27+
/**
28+
* {@inheritdoc}
29+
*/
30+
public function sendRequest(RequestInterface $request)
31+
{
32+
$client = $this->chooseHttpClient($request);
33+
34+
return $client->sendRequest($request);
35+
}
36+
37+
/**
38+
* Add a client to the router
39+
*
40+
* @param HttpClient|HttpAsyncClient $client
41+
* @param RequestMatcher $requestMatcher
42+
*/
43+
public function addClient($client, RequestMatcher $requestMatcher)
44+
{
45+
$this->clients[] = [
46+
'matcher' => $requestMatcher,
47+
'client' => new HttpClientFlexible($client)
48+
];
49+
}
50+
51+
/**
52+
* Choose a http client given a specific request
53+
*
54+
* @param RequestInterface $request
55+
*
56+
* @return HttpClient|HttpAsyncClient
57+
*/
58+
protected function chooseHttpClient(RequestInterface $request)
59+
{
60+
foreach ($this->clients as $client) {
61+
if ($client['matcher']->matches($request)) {
62+
return $client['client'];
63+
}
64+
}
65+
66+
throw new RequestException('No client found for the specified request', $request);
67+
}
68+
}

src/RequestMatcher.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Http\Client\Common;
4+
use Psr\Http\Message\RequestInterface;
5+
6+
/**
7+
* RequestMatcher allow to tell if a PSR7 Request matches a specific strategy
8+
*
9+
* @author Joel Wurtz <[email protected]>
10+
*/
11+
interface RequestMatcher
12+
{
13+
/**
14+
* Whether the request matches a specific strategy
15+
*
16+
* @param RequestInterface $request
17+
*
18+
* @return boolean
19+
*/
20+
public function matches(RequestInterface $request);
21+
}

0 commit comments

Comments
 (0)