Skip to content

Commit fd63989

Browse files
authored
Merge pull request #33 from sunrise-php/release/v1.4.4
v1.4.4
2 parents b2c4c41 + 8540c02 commit fd63989

File tree

7 files changed

+78
-65
lines changed

7 files changed

+78
-65
lines changed

.circleci/config.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,39 @@ jobs:
1010
steps:
1111
- checkout
1212
- run: php -v
13-
- run: composer install --no-interaction --no-suggest --prefer-source
13+
- run: composer install --no-interaction
1414
- run: XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text
1515
php72:
1616
docker:
1717
- image: circleci/php:7.2-cli-node-browsers
1818
steps:
1919
- checkout
2020
- run: php -v
21-
- run: composer install --no-interaction --no-suggest --prefer-source
21+
- run: composer install --no-interaction
2222
- run: XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text
2323
php73:
2424
docker:
2525
- image: circleci/php:7.3-cli-node-browsers
2626
steps:
2727
- checkout
2828
- run: php -v
29-
- run: composer install --no-interaction --no-suggest --prefer-source
29+
- run: composer install --no-interaction
3030
- run: XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text
3131
php74:
3232
docker:
3333
- image: circleci/php:7.4-cli-node-browsers
3434
steps:
3535
- checkout
3636
- run: php -v
37-
- run: composer install --no-interaction --no-suggest --prefer-source
37+
- run: composer install --no-interaction
3838
- run: XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text
3939
php80:
4040
docker:
4141
- image: circleci/php:8.0-cli-node-browsers
4242
steps:
4343
- checkout
4444
- run: php -v
45-
- run: composer install --no-interaction --no-suggest --prefer-source
45+
- run: composer install --no-interaction
4646
- run: XDEBUG_MODE=coverage php vendor/bin/phpunit --coverage-text
4747
workflows:
4848
version: 2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
/phpbench.json
66
/phpcs.xml
77
/phpunit.xml
8+
/psalm.xml
89
/vendor/

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# HTTP cURL client for PHP 7.1+ (incl. PHP 8) based on PSR-18
1+
# Simple HTTP cURL client for PHP 7.1+ based on PSR-18
22

33
[![Build Status](https://circleci.com/gh/sunrise-php/http-client-curl.svg?style=shield)](https://circleci.com/gh/sunrise-php/http-client-curl)
44
[![Code Coverage](https://scrutinizer-ci.com/g/sunrise-php/http-client-curl/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/sunrise-php/http-client-curl/?branch=master)

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sunrise/http-client-curl",
33
"homepage": "https://github.com/sunrise-php/http-client-curl",
4-
"description": "Sunrise // HTTP cURL client for PHP 7.1+ (incl. PHP 8) based on PSR-18",
4+
"description": "Simple HTTP cURL client for PHP 7.1+ based on PSR-18",
55
"license": "MIT",
66
"keywords": [
77
"fenric",
@@ -20,7 +20,7 @@
2020
{
2121
"name": "Anatoly Fenric",
2222
"email": "anatoly@fenric.ru",
23-
"homepage": "https://anatoly.fenric.ru/"
23+
"homepage": "https://github.com/fenric"
2424
},
2525
{
2626
"name": "李昀陞 (Peter)",
@@ -52,6 +52,7 @@
5252
"scripts": {
5353
"test": [
5454
"phpcs",
55+
"psalm",
5556
"XDEBUG_MODE=coverage phpunit --coverage-text --colors=always"
5657
],
5758
"build": [

psalm.xml.dist

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0"?>
2+
<psalm
3+
errorLevel="1"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns="https://getpsalm.org/schema/config"
6+
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
7+
>
8+
<projectFiles>
9+
<directory name="src" />
10+
<ignoreFiles>
11+
<directory name="vendor" />
12+
</ignoreFiles>
13+
</projectFiles>
14+
</psalm>

src/Client.php

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
*/
1717
use Psr\Http\Client\ClientInterface;
1818
use Psr\Http\Message\RequestInterface;
19-
use Psr\Http\Message\ResponseInterface;
2019
use Psr\Http\Message\ResponseFactoryInterface;
20+
use Psr\Http\Message\ResponseInterface;
2121
use Sunrise\Http\Client\Curl\Exception\ClientException;
2222
use Sunrise\Http\Client\Curl\Exception\NetworkException;
2323

@@ -30,18 +30,18 @@
3030
use function curl_exec;
3131
use function curl_getinfo;
3232
use function curl_init;
33-
use function curl_multi_init;
34-
use function curl_multi_exec;
3533
use function curl_multi_add_handle;
36-
use function curl_multi_remove_handle;
3734
use function curl_multi_close;
35+
use function curl_multi_exec;
36+
use function curl_multi_init;
37+
use function curl_multi_remove_handle;
3838
use function curl_setopt_array;
3939
use function explode;
4040
use function in_array;
41+
use function ltrim;
4142
use function sprintf;
4243
use function strpos;
4344
use function substr;
44-
use function trim;
4545

4646
/**
4747
* Import constants
@@ -136,8 +136,8 @@ public function sendRequests(RequestInterface ...$requests) : array
136136
}
137137

138138
do {
139-
curl_multi_exec($curlMultiHandle, $active);
140-
} while ($active);
139+
curl_multi_exec($curlMultiHandle, $isActive);
140+
} while ($isActive);
141141

142142
$responses = [];
143143
foreach ($curlHandles as $i => $curlHandle) {
@@ -152,7 +152,7 @@ public function sendRequests(RequestInterface ...$requests) : array
152152
}
153153

154154
/**
155-
* Creates CurlHandle using the given request
155+
* Creates a CurlHandle from the given request
156156
*
157157
* @param RequestInterface $request
158158
*
@@ -174,6 +174,7 @@ private function createCurlHandleFromRequest(RequestInterface $request)
174174
$curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
175175
}
176176

177+
$curlOptions[CURLOPT_HTTPHEADER] = [];
177178
foreach ($request->getHeaders() as $name => $values) {
178179
foreach ($values as $value) {
179180
$curlOptions[CURLOPT_HTTPHEADER][] = sprintf('%s: %s', $name, $value);
@@ -194,29 +195,33 @@ private function createCurlHandleFromRequest(RequestInterface $request)
194195
}
195196

196197
/**
197-
* Creates response using the given CurlHandle
198+
* Creates a response from the given CurlHandle
198199
*
199200
* @param resource $curlHandle
200201
*
201202
* @return ResponseInterface
202203
*/
203204
private function createResponseFromCurlHandle($curlHandle) : ResponseInterface
204205
{
205-
$rescode = curl_getinfo($curlHandle, CURLINFO_RESPONSE_CODE);
206-
$response = $this->responseFactory->createResponse($rescode);
206+
/** @var int */
207+
$statusCode = curl_getinfo($curlHandle, CURLINFO_RESPONSE_CODE);
208+
$response = $this->responseFactory->createResponse($statusCode);
207209

208-
$reqtime = curl_getinfo($curlHandle, CURLINFO_TOTAL_TIME);
209-
$response = $response->withAddedHeader('X-Request-Time', sprintf('%.3f ms', $reqtime * 1000));
210+
/** @var float */
211+
$totalTime = curl_getinfo($curlHandle, CURLINFO_TOTAL_TIME);
212+
$response = $response->withAddedHeader('X-Request-Time', sprintf('%.3f ms', $totalTime * 1000));
210213

214+
/** @var ?string */
211215
$message = curl_multi_getcontent($curlHandle);
212216
if ($message === null) {
213217
return $response;
214218
}
215219

220+
/** @var int */
216221
$headerSize = curl_getinfo($curlHandle, CURLINFO_HEADER_SIZE);
217222

218223
$header = substr($message, 0, $headerSize);
219-
$response = $this->fillResponseWithHeaderFields($response, $header);
224+
$response = $this->populateResponseWithHeaderFields($response, $header);
220225

221226
$body = substr($message, $headerSize);
222227
$response->getBody()->write($body);
@@ -225,27 +230,38 @@ private function createResponseFromCurlHandle($curlHandle) : ResponseInterface
225230
}
226231

227232
/**
228-
* Fills the given response with the header fields using the given header
233+
* Populates the given response with the given header's fields
229234
*
230235
* @param ResponseInterface $response
231236
* @param string $header
232237
*
233238
* @return ResponseInterface
239+
*
240+
* @link https://datatracker.ietf.org/doc/html/rfc2616#section-4.2
234241
*/
235-
private function fillResponseWithHeaderFields(ResponseInterface $response, string $header) : ResponseInterface
242+
private function populateResponseWithHeaderFields(ResponseInterface $response, string $header) : ResponseInterface
236243
{
237-
$fields = explode("\n", $header);
244+
$fields = explode("\r\n", $header);
245+
238246
foreach ($fields as $field) {
239-
$colpos = strpos($field, ':');
240-
if ($colpos === false) { // Status Line
247+
// status line
248+
if (0 === strpos($field, 'HTTP/')) {
241249
continue;
242-
} elseif ($colpos === 0) { // HTTP/2 Field
250+
}
251+
252+
// HTTP/2 field
253+
if (0 === strpos($field, ':')) {
254+
continue;
255+
}
256+
257+
// end...
258+
if ('' === $field) {
243259
continue;
244260
}
245261

246-
list($name, $value) = explode(':', $field, 2);
262+
[$name, $value] = explode(':', $field, 2);
247263

248-
$response = $response->withAddedHeader(trim($name), trim($value));
264+
$response = $response->withAddedHeader($name, ltrim($value));
249265
}
250266

251267
return $response;

tests/ClientTest.php

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,28 @@ public function testConstructor()
2828

2929
public function testSendRequest()
3030
{
31-
$url = 'https://raw.githubusercontent.com';
32-
$url .= '/sunrise-php/http-client-curl/dea2ea60d8d5b9f0839d8dba8cd714213c1c2b50/LICENSE';
3331
$client = new Client(new ResponseFactory());
34-
$request = (new RequestFactory)->createRequest('GET', $url);
32+
$request = (new RequestFactory)->createRequest('GET', 'https://www.php.net/');
3533
$response = $client->sendRequest($request);
3634
$this->assertInstanceOf(ResponseInterface::class, $response);
3735
$this->assertSame(200, $response->getStatusCode());
38-
$this->assertSame('text/plain; charset=utf-8', $response->getHeaderLine('content-type'));
3936
$this->assertTrue($response->hasHeader('X-Request-Time'));
4037
}
4138

4239
public function testSendRequests()
4340
{
44-
$requests = [];
45-
46-
$url = 'https://raw.githubusercontent.com';
47-
$url .= '/sunrise-php/http-client-curl/dea2ea60d8d5b9f0839d8dba8cd714213c1c2b50/LICENSE';
48-
$requests[] = (new RequestFactory)->createRequest('GET', $url);
49-
50-
$url = 'https://raw.githubusercontent.com';
51-
$url .= '/sunrise-php/http-client-curl/b52d6cf88186101562ed93d9dbbb909ae82924d4/README.md';
52-
$requests[] = (new RequestFactory)->createRequest('GET', $url);
53-
5441
$client = new Client(new ResponseFactory());
42+
$requests = [];
43+
$requests[] = (new RequestFactory)->createRequest('GET', 'https://www.php.net/');
44+
$requests[] = (new RequestFactory)->createRequest('GET', 'https://www.php.net/');
5545
$responses = $client->sendRequests(...$requests);
5646

5747
$this->assertInstanceOf(ResponseInterface::class, $responses[0]);
5848
$this->assertSame(200, $responses[0]->getStatusCode());
59-
$this->assertSame('OK', $responses[0]->getReasonPhrase());
60-
$this->assertSame('text/plain; charset=utf-8', $responses[0]->getHeaderLine('content-type'));
6149
$this->assertTrue($responses[0]->hasHeader('X-Request-Time'));
6250

6351
$this->assertInstanceOf(ResponseInterface::class, $responses[1]);
6452
$this->assertSame(200, $responses[1]->getStatusCode());
65-
$this->assertSame('text/plain; charset=utf-8', $responses[1]->getHeaderLine('content-type'));
6653
$this->assertTrue($responses[1]->hasHeader('X-Request-Time'));
6754
}
6855

@@ -78,50 +65,44 @@ public function testSendRequestWithEmptyUri()
7865

7966
public function testClientException()
8067
{
81-
$message = 'foo';
82-
$code = 1;
83-
$previous = new RuntimeException('bar');
68+
$previous = new RuntimeException();
8469

85-
$exception = new ClientException($message, $code, $previous);
70+
$exception = new ClientException('foo', 42, $previous);
8671
$this->assertInstanceOf(RuntimeException::class, $exception);
8772
$this->assertInstanceOf(ClientExceptionInterface::class, $exception);
8873

89-
$this->assertSame($message, $exception->getMessage());
90-
$this->assertSame($code, $exception->getCode());
74+
$this->assertSame('foo', $exception->getMessage());
75+
$this->assertSame(42, $exception->getCode());
9176
$this->assertSame($previous, $exception->getPrevious());
9277
}
9378

9479
public function testNetworkException()
9580
{
9681
$request = (new RequestFactory)->createRequest('GET', 'http://php.net/');
97-
$message = 'foo';
98-
$code = 1;
99-
$previous = new RuntimeException('bar');
82+
$previous = new RuntimeException();
10083

101-
$exception = new NetworkException($request, $message, $code, $previous);
84+
$exception = new NetworkException($request, 'foo', 42, $previous);
10285
$this->assertInstanceOf(ClientException::class, $exception);
10386
$this->assertInstanceOf(NetworkExceptionInterface::class, $exception);
10487

10588
$this->assertSame($request, $exception->getRequest());
106-
$this->assertSame($message, $exception->getMessage());
107-
$this->assertSame($code, $exception->getCode());
89+
$this->assertSame('foo', $exception->getMessage());
90+
$this->assertSame(42, $exception->getCode());
10891
$this->assertSame($previous, $exception->getPrevious());
10992
}
11093

11194
public function testRequestException()
11295
{
11396
$request = (new RequestFactory)->createRequest('GET', 'http://php.net/');
114-
$message = 'foo';
115-
$code = 1;
116-
$previous = new RuntimeException('bar');
97+
$previous = new RuntimeException();
11798

118-
$exception = new RequestException($request, $message, $code, $previous);
99+
$exception = new RequestException($request, 'foo', 42, $previous);
119100
$this->assertInstanceOf(ClientException::class, $exception);
120101
$this->assertInstanceOf(RequestExceptionInterface::class, $exception);
121102

122103
$this->assertSame($request, $exception->getRequest());
123-
$this->assertSame($message, $exception->getMessage());
124-
$this->assertSame($code, $exception->getCode());
104+
$this->assertSame('foo', $exception->getMessage());
105+
$this->assertSame(42, $exception->getCode());
125106
$this->assertSame($previous, $exception->getPrevious());
126107
}
127108
}

0 commit comments

Comments
 (0)