Skip to content
This repository was archived by the owner on Jan 6, 2024. It is now read-only.

Commit 479c110

Browse files
committed
Merge pull request #3 from php-http/client_separation
Client separation
2 parents dd2583e + dedb19e commit 479c110

File tree

2 files changed

+136
-101
lines changed

2 files changed

+136
-101
lines changed

composer.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@
88
{
99
"name": "Eric GELOEN",
1010
"email": "[email protected]"
11+
},
12+
{
13+
"name": "Márk Sági-Kazár",
14+
"email": "[email protected]"
1115
}
1216
],
1317
"require": {
1418
"php": ">=5.4",
15-
"php-http/adapter-core": "dev-internal_separation",
19+
"php-http/adapter-common": "dev-master",
20+
"php-http/common": "dev-master",
1621
"guzzlehttp/guzzle": "~5.1",
1722
"guzzlehttp/ringphp": "^1.0.8@dev"
1823
},
1924
"require-dev": {
2025
"ext-curl": "*",
21-
"php-http/adapter-integration-tests": "dev-internal_separation"
26+
"php-http/adapter-integration-tests": "dev-contract_changes"
2227
},
2328
"provide": {
2429
"php-http/adapter-implementation": "0.1"

src/Guzzle5HttpAdapter.php

Lines changed: 129 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,26 @@
1313

1414
use GuzzleHttp\Client;
1515
use GuzzleHttp\ClientInterface;
16-
use GuzzleHttp\Event\CompleteEvent;
17-
use GuzzleHttp\Event\ErrorEvent;
1816
use GuzzleHttp\Exception\RequestException;
19-
use GuzzleHttp\Message\RequestInterface;
17+
use GuzzleHttp\Message\RequestInterface as GuzzleRequest;
18+
use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
2019
use GuzzleHttp\Pool;
21-
use Http\Adapter\Common\Exception\CannotFetchUri;
22-
use Http\Adapter\Internal\Message\InternalRequest;
23-
use Http\Adapter\Internal\Message\MessageFactory;
24-
use Http\Adapter\Normalizer\BodyNormalizer;
20+
use Http\Adapter\Common\Exception\HttpAdapterException;
21+
use Http\Adapter\Common\Exception\MultiHttpAdapterException;
22+
use Http\Common\Message\MessageFactoryGuesser;
23+
use Http\Message\MessageFactory;
24+
use Http\Message\MessageFactoryAware;
25+
use Http\Message\MessageFactoryAwareTemplate;
26+
use Psr\Http\Message\RequestInterface;
27+
use Psr\Http\Message\ResponseInterface;
2528

2629
/**
2730
* @author GeLo <[email protected]>
2831
*/
29-
class Guzzle5HttpAdapter extends Core\CurlHttpAdapter
32+
class Guzzle5HttpAdapter implements HttpAdapter, MessageFactoryAware
3033
{
34+
use MessageFactoryAwareTemplate;
35+
3136
/**
3237
* @var ClientInterface
3338
*/
@@ -36,138 +41,163 @@ class Guzzle5HttpAdapter extends Core\CurlHttpAdapter
3641
/**
3742
*
3843
* @param ClientInterface|null $client
39-
* @param array $options
4044
* @param MessageFactory|null $messageFactory
4145
*/
42-
public function __construct(ClientInterface $client = null, array $options = [], MessageFactory $messageFactory = null)
46+
public function __construct(ClientInterface $client = null, MessageFactory $messageFactory = null)
4347
{
44-
parent::__construct($options, $messageFactory);
45-
4648
$this->client = $client ?: new Client();
47-
}
49+
$this->messageFactory = $messageFactory ?: MessageFactoryGuesser::guess();
4850

49-
/**
50-
* {@inheritdoc}
51-
*/
52-
public function getName()
53-
{
54-
return 'guzzle5';
5551
}
5652

5753
/**
5854
* {@inheritdoc}
5955
*/
60-
protected function sendInternalRequest(InternalRequest $internalRequest)
56+
public function sendRequest(RequestInterface $request, array $options = [])
6157
{
58+
$guzzleRequest = $this->createRequest($request, $options);
59+
6260
try {
63-
$response = $this->client->send($this->createRequest($internalRequest));
61+
$response = $this->client->send($guzzleRequest);
6462
} catch (RequestException $e) {
65-
throw new CannotFetchUri($e->getRequest()->getUrl(), $this->getName(), $e);
63+
throw $this->createException($e, $request);
6664
}
6765

68-
return $this->getMessageFactory()->createResponse(
69-
(integer) $response->getStatusCode(),
70-
null,
71-
$response->getProtocolVersion(),
72-
$response->getHeaders(),
73-
BodyNormalizer::normalize(
74-
function () use ($response) {
75-
return $response->getBody()->detach();
76-
},
77-
$internalRequest->getMethod()
78-
)
79-
);
66+
return $this->createResponse($response);
8067
}
8168

8269
/**
8370
* {@inheritdoc}
8471
*/
85-
protected function sendInternalRequests(array $internalRequests, callable $success, callable $error)
72+
public function sendRequests(array $requests, array $options = [])
8673
{
87-
$requests = [];
88-
foreach ($internalRequests as $internalRequest) {
89-
$requests[] = $this->createRequest($internalRequest, $success, $error);
74+
$requests = array_values($requests);
75+
$guzzleRequests = [];
76+
77+
foreach ($requests as $request) {
78+
$guzzleRequests[] = $this->createRequest($request, $options);
79+
}
80+
81+
$results = Pool::batch($this->client, $guzzleRequests);
82+
83+
$exceptions = [];
84+
$responses = [];
85+
86+
foreach ($guzzleRequests as $key => $guzzleRequest) {
87+
$result = $results->getResult($guzzleRequest);
88+
89+
if ($result instanceof GuzzleResponse) {
90+
$responses[] = $this->createResponse($result);
91+
} elseif ($result instanceof RequestException) {
92+
$exceptions[] = $this->createException($result, $requests[$key]);
93+
}
9094
}
9195

92-
Pool::batch($this->client, $requests);
96+
if (count($exceptions) > 0) {
97+
throw new MultiHttpAdapterException($exceptions, $responses);
98+
}
99+
100+
return $responses;
93101
}
94102

95103
/**
96104
* {@inheritdoc}
97105
*/
98-
protected function createFile($file)
106+
public function getName()
107+
{
108+
return 'guzzle5';
109+
}
110+
111+
/**
112+
* Converts a PSR request into a Guzzle request
113+
*
114+
* @param RequestInterface $request
115+
*
116+
* @return GuzzleRequest
117+
*/
118+
private function createRequest(RequestInterface $request, array $options = [])
99119
{
100-
return fopen($file, 'r');
120+
$options = $this->buildOptions($options);
121+
122+
$options['version'] = $request->getProtocolVersion();
123+
$options['headers'] = $request->getHeaders();
124+
$options['body'] = (string) $request->getBody();
125+
126+
return $this->client->createRequest(
127+
$request->getMethod(),
128+
(string) $request->getUri(),
129+
$options
130+
);
101131
}
102132

103133
/**
104-
* Creates a request
134+
* Converts a Guzzle response into a PSR response
105135
*
106-
* @param InternalRequest $internalRequest
107-
* @param callable|null $success
108-
* @param callable|null $error
136+
* @param GuzzleResponse $response
109137
*
110-
* @return RequestInterface
138+
* @return ResponseInterface
111139
*/
112-
private function createRequest(InternalRequest $internalRequest, callable $success = null, callable $error = null)
140+
private function createResponse(GuzzleResponse $response)
113141
{
114-
$request = $this->client->createRequest(
115-
$internalRequest->getMethod(),
116-
(string) $internalRequest->getUri(),
117-
[
118-
'exceptions' => false,
119-
'allow_redirects' => false,
120-
'timeout' => $this->getContextOption('timeout', $internalRequest),
121-
'connect_timeout' => $this->getContextOption('timeout', $internalRequest),
122-
'version' => $internalRequest->getProtocolVersion(),
123-
'headers' => $this->prepareHeaders($internalRequest),
124-
'body' => $this->prepareContent($internalRequest),
125-
]
142+
$body = $response->getBody();
143+
144+
return $this->getMessageFactory()->createResponse(
145+
$response->getStatusCode(),
146+
null,
147+
$response->getProtocolVersion(),
148+
$response->getHeaders(),
149+
isset($body) ? $body->detach() : null
150+
);
151+
}
152+
153+
/**
154+
* Converts a Guzzle exception into an HttpAdapter exception
155+
*
156+
* @param RequestException $exception
157+
*
158+
* @return HttpAdapterException
159+
*/
160+
private function createException(
161+
RequestException $exception,
162+
RequestInterface $originalRequest
163+
) {
164+
$adapterException = new HttpAdapterException(
165+
$exception->getMessage(),
166+
0,
167+
$exception
126168
);
127169

128-
if (isset($success)) {
129-
$messageFactory = $this->getMessageFactory();
130-
131-
$request->getEmitter()->on(
132-
'complete',
133-
function (CompleteEvent $event) use ($success, $internalRequest, $messageFactory) {
134-
$response = $messageFactory->createResponse(
135-
(integer) $event->getResponse()->getStatusCode(),
136-
null,
137-
$event->getResponse()->getProtocolVersion(),
138-
$event->getResponse()->getHeaders(),
139-
BodyNormalizer::normalize(
140-
function () use ($event) {
141-
return $event->getResponse()->getBody()->detach();
142-
},
143-
$internalRequest->getMethod()
144-
)
145-
);
146-
147-
$response = new Core\Message\ParameterableResponse($response);
148-
$response = $response->withParameter('request', $internalRequest);
149-
call_user_func($success, $response);
150-
}
151-
);
170+
$response = null;
171+
172+
if ($exception->hasResponse()) {
173+
$response = $this->createResponse($exception->getResponse());
152174
}
153175

154-
if (isset($error)) {
155-
$httpAdapterName = $this->getName();
156-
157-
$request->getEmitter()->on(
158-
'error',
159-
function (ErrorEvent $event) use ($error, $internalRequest, $httpAdapterName) {
160-
$exception = new CannotFetchUri(
161-
$event->getException()->getRequest()->getUrl(),
162-
$httpAdapterName,
163-
$event->getException()
164-
);
165-
$exception->setRequest($internalRequest);
166-
call_user_func($error, $exception);
167-
}
168-
);
176+
$adapterException->setResponse($response);
177+
$adapterException->setRequest($originalRequest);
178+
179+
return $adapterException;
180+
}
181+
182+
/**
183+
* Builds options for Guzzle
184+
*
185+
* @param array $options
186+
*
187+
* @return array
188+
*/
189+
private function buildOptions(array $options)
190+
{
191+
$guzzleOptions = [
192+
'exceptions' => false,
193+
'allow_redirects' => false,
194+
];
195+
196+
if (isset($options['timeout'])) {
197+
$guzzleOptions['connect_timeout'] = $options['timeout'];
198+
$guzzleOptions['timeout'] = $options['timeout'];
169199
}
170200

171-
return $request;
201+
return $guzzleOptions;
172202
}
173203
}

0 commit comments

Comments
 (0)