Skip to content

Commit c4a3d97

Browse files
committed
Refactoring.
1 parent 31789de commit c4a3d97

File tree

1 file changed

+84
-109
lines changed

1 file changed

+84
-109
lines changed

src/CurlHttpClient.php

Lines changed: 84 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,27 @@ class CurlHttpClient implements HttpClient
3535

3636
/**
3737
* cURL handle opened resource
38-
* @var resource
38+
*
39+
* @var resource|null
3940
*/
40-
private $handle;
41+
private $handle = null;
4142

4243
/**
43-
* cURL handle configuration TODO change description
44+
* Client settings
4445
*
4546
* @var array
46-
*
47-
* @since 1.00
4847
*/
49-
protected $options;
48+
private $settings;
5049

5150
/**
52-
* Constructor
51+
* Create new client
5352
*
54-
* Available options (see also {@link getDefaultOptions}):
53+
* Available options:
5554
*
56-
* - connection_timeout : int — connection timeout in seconds
57-
* - ssl_verify_peer : bool — verify peer when using SSL
58-
* - timeout : int — overall timeout in seconds
55+
* - connection_timeout : int — connection timeout in seconds;
56+
* - curl_options: array — custom cURL options;
57+
* - ssl_verify_peer : bool — verify peer when using SSL;
58+
* - timeout : int — overall timeout in seconds.
5959
*
6060
* @param MessageFactory $messageFactory HTTP Message factory
6161
* @param StreamFactory $streamFactory HTTP Stream factory
@@ -70,12 +70,14 @@ public function __construct(
7070
) {
7171
$this->setMessageFactory($messageFactory);
7272
$this->setStreamFactory($streamFactory);
73-
$this->options = array_merge(
74-
$this->getDefaultOptions(),
75-
array_intersect_key(
76-
$options,
77-
$this->getDefaultOptions()
78-
)
73+
$this->settings = array_merge(
74+
[
75+
'curl_options' => [],
76+
'connection_timeout' => 3,
77+
'ssl_verify_peer' => true,
78+
'timeout' => 10
79+
],
80+
$options
7981
);
8082
}
8183

@@ -89,23 +91,6 @@ public function __destruct()
8991
}
9092
}
9193

92-
/**
93-
* Return available options and there default values
94-
*
95-
* @return array
96-
*
97-
* @since 1.00
98-
*/
99-
public function getDefaultOptions()
100-
{
101-
return [
102-
'curl_options' => [],
103-
'connection_timeout' => 3,
104-
'ssl_verify_peer' => true,
105-
'timeout' => 10
106-
];
107-
}
108-
10994
/**
11095
* Sends a PSR-7 request.
11196
*
@@ -158,12 +143,19 @@ public function sendRequest(RequestInterface $request)
158143
$parts = explode(':', $header, 2);
159144
$headerName = trim(urldecode($parts[0]));
160145
$headerValue = trim(urldecode($parts[1]));
161-
$response = $this->addHeaderToResponse($response, $headerName, $headerValue);
146+
if ($response->hasHeader($headerName)) {
147+
$response = $response->withAddedHeader($headerName, $headerValue);
148+
} else {
149+
$response = $response->withHeader($headerName, $headerValue);
150+
}
162151
}
163152

153+
/*
154+
* substr can return boolean value for empty string. But createStream does not support
155+
* booleans. Converting to string.
156+
*/
164157
$content = (string) substr($raw, $headerSize);
165158
$stream = $this->getStreamFactory()->createStream($content);
166-
/** @var ResponseInterface $response */
167159
$response = $response->withBody($stream);
168160

169161
return $response;
@@ -188,43 +180,19 @@ protected function request($options, &$raw, &$info)
188180
$this->handle = curl_init();
189181
}
190182

191-
try {
192-
curl_setopt_array($this->handle, $options);
193-
$raw = curl_exec($this->handle);
183+
curl_setopt_array($this->handle, $options);
184+
$raw = curl_exec($this->handle);
194185

195-
if (curl_errno($this->handle) > 0) {
196-
throw new RuntimeException(
197-
sprintf(
198-
'Curl error: (%d) %s',
199-
curl_errno($this->handle),
200-
curl_error($this->handle)
201-
)
202-
);
203-
}
204-
$info = curl_getinfo($this->handle);
205-
} finally {
186+
if (curl_errno($this->handle) > 0) {
187+
throw new RuntimeException(
188+
sprintf(
189+
'Curl error: (%d) %s',
190+
curl_errno($this->handle),
191+
curl_error($this->handle)
192+
)
193+
);
206194
}
207-
}
208-
209-
/**
210-
* Adds a header to the response object
211-
*
212-
* @param ResponseInterface $response
213-
* @param string $name
214-
* @param string $value
215-
*
216-
* @return ResponseInterface
217-
*
218-
* @since 1.00
219-
*/
220-
protected function addHeaderToResponse($response, $name, $value)
221-
{
222-
if ($response->hasHeader($name)) {
223-
$response = $response->withAddedHeader($name, $value);
224-
} else {
225-
$response = $response->withHeader($name, $value);
226-
}
227-
return $response;
195+
$info = curl_getinfo($this->handle);
228196
}
229197

230198
/**
@@ -238,57 +206,36 @@ protected function addHeaderToResponse($response, $name, $value)
238206
*/
239207
private function createCurlOptions(RequestInterface $request)
240208
{
241-
$options = array_key_exists('curl_options', $this->options)
242-
? $this->options['curl_options']
243-
: [];
209+
$options = $this->settings['curl_options'];
244210

245211
$options[CURLOPT_HEADER] = true;
246212
$options[CURLOPT_RETURNTRANSFER] = true;
247213

248214
$options[CURLOPT_HTTP_VERSION] = $this->getProtocolVersion($request->getProtocolVersion());
249215
$options[CURLOPT_URL] = (string) $request->getUri();
250216

251-
$options[CURLOPT_CONNECTTIMEOUT] = $this->options['connection_timeout'];
217+
$options[CURLOPT_CONNECTTIMEOUT] = $this->settings['connection_timeout'];
252218
$options[CURLOPT_FOLLOWLOCATION] = false;
253-
$options[CURLOPT_SSL_VERIFYPEER] = $this->options['ssl_verify_peer'];
254-
$options[CURLOPT_TIMEOUT] = $this->options['timeout'];
219+
$options[CURLOPT_SSL_VERIFYPEER] = $this->settings['ssl_verify_peer'];
220+
$options[CURLOPT_TIMEOUT] = $this->settings['timeout'];
255221

256-
switch ($request->getMethod()) {
257-
case 'HEAD':
258-
$options[CURLOPT_NOBODY] = true;
259-
break;
260-
case 'OPTIONS':
261-
case 'POST':
262-
case 'PUT':
263-
$options[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
264-
$body = (string) $request->getBody();
265-
if ('' !== $body) {
266-
$options[CURLOPT_POSTFIELDS] = $body;
267-
}
268-
break;
269-
case 'CONNECT':
270-
case 'DELETE':
271-
case 'PATCH':
272-
case 'TRACE':
273-
$options[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
274-
break;
222+
if (in_array($request->getMethod(), ['OPTIONS', 'POST', 'PUT'], true)) {
223+
/* cURL allows request body only for these methods. */
224+
$body = (string) $request->getBody();
225+
if ('' !== $body) {
226+
$options[CURLOPT_POSTFIELDS] = $body;
227+
}
275228
}
276229

277-
$headers = array_keys($request->getHeaders());
278-
foreach ($headers as $name) {
279-
if (strtolower($name) === 'content-length') {
280-
$values = [0];
281-
if (array_key_exists(CURLOPT_POSTFIELDS, $options)) {
282-
$values = [strlen($options[CURLOPT_POSTFIELDS])];
283-
}
284-
} else {
285-
$values = $request->getHeader($name);
286-
}
287-
foreach ($values as $value) {
288-
$options[CURLOPT_HTTPHEADER][] = $name . ': ' . $value;
289-
}
230+
if ($request->getMethod() === 'HEAD') {
231+
$options[CURLOPT_NOBODY] = true;
232+
} elseif ($request->getMethod() !== 'GET') {
233+
/* GET is a default method. Other methods should be specified explicitly. */
234+
$options[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
290235
}
291236

237+
$options[CURLOPT_HTTPHEADER] = $this->createHeaders($request, $options);
238+
292239
if ($request->getUri()->getUserInfo()) {
293240
$options[CURLOPT_USERPWD] = $request->getUri()->getUserInfo();
294241
}
@@ -320,4 +267,32 @@ private function getProtocolVersion($requestVersion)
320267
}
321268
return CURL_HTTP_VERSION_NONE;
322269
}
270+
271+
/**
272+
* Create headers array for CURLOPT_HTTPHEADER
273+
*
274+
* @param RequestInterface $request
275+
* @param array $options cURL options
276+
*
277+
* @return string[]
278+
*/
279+
private function createHeaders(RequestInterface $request, array $options)
280+
{
281+
$curlHeaders = [];
282+
$headers = array_keys($request->getHeaders());
283+
foreach ($headers as $name) {
284+
if (strtolower($name) === 'content-length') {
285+
$values = [0];
286+
if (array_key_exists(CURLOPT_POSTFIELDS, $options)) {
287+
$values = [strlen($options[CURLOPT_POSTFIELDS])];
288+
}
289+
} else {
290+
$values = $request->getHeader($name);
291+
}
292+
foreach ($values as $value) {
293+
$curlHeaders[] = $name . ': ' . $value;
294+
}
295+
}
296+
return $curlHeaders;
297+
}
323298
}

0 commit comments

Comments
 (0)