Skip to content

Commit

Permalink
minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Анатолий Нехай committed Apr 17, 2022
1 parent cb74d32 commit c9e9e1b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 57 deletions.
60 changes: 38 additions & 22 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
*/
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Sunrise\Http\Client\Curl\Exception\ClientException;
use Sunrise\Http\Client\Curl\Exception\NetworkException;

Expand All @@ -30,18 +30,18 @@
use function curl_exec;
use function curl_getinfo;
use function curl_init;
use function curl_multi_init;
use function curl_multi_exec;
use function curl_multi_add_handle;
use function curl_multi_remove_handle;
use function curl_multi_close;
use function curl_multi_exec;
use function curl_multi_init;
use function curl_multi_remove_handle;
use function curl_setopt_array;
use function explode;
use function in_array;
use function ltrim;
use function sprintf;
use function strpos;
use function substr;
use function trim;

/**
* Import constants
Expand Down Expand Up @@ -136,8 +136,8 @@ public function sendRequests(RequestInterface ...$requests) : array
}

do {
curl_multi_exec($curlMultiHandle, $active);
} while ($active);
curl_multi_exec($curlMultiHandle, $isActive);
} while ($isActive);

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

/**
* Creates CurlHandle using the given request
* Creates a CurlHandle from the given request
*
* @param RequestInterface $request
*
Expand All @@ -174,6 +174,7 @@ private function createCurlHandleFromRequest(RequestInterface $request)
$curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
}

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

/**
* Creates response using the given CurlHandle
* Creates a response from the given CurlHandle
*
* @param resource $curlHandle
*
* @return ResponseInterface
*/
private function createResponseFromCurlHandle($curlHandle) : ResponseInterface
{
$rescode = curl_getinfo($curlHandle, CURLINFO_RESPONSE_CODE);
$response = $this->responseFactory->createResponse($rescode);
/** @var int */
$statusCode = curl_getinfo($curlHandle, CURLINFO_RESPONSE_CODE);
$response = $this->responseFactory->createResponse($statusCode);

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

/** @var ?string */
$message = curl_multi_getcontent($curlHandle);
if ($message === null) {
return $response;
}

/** @var int */
$headerSize = curl_getinfo($curlHandle, CURLINFO_HEADER_SIZE);

$header = substr($message, 0, $headerSize);
$response = $this->fillResponseWithHeaderFields($response, $header);
$response = $this->populateResponseWithHeaderFields($response, $header);

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

/**
* Fills the given response with the header fields using the given header
* Populates the given response with the given header's fields
*
* @param ResponseInterface $response
* @param string $header
*
* @return ResponseInterface
*
* @link https://datatracker.ietf.org/doc/html/rfc2616#section-4.2
*/
private function fillResponseWithHeaderFields(ResponseInterface $response, string $header) : ResponseInterface
private function populateResponseWithHeaderFields(ResponseInterface $response, string $header) : ResponseInterface
{
$fields = explode("\n", $header);
$fields = explode("\r\n", $header);

foreach ($fields as $field) {
$colpos = strpos($field, ':');
if ($colpos === false) { // Status Line
// status line
if (0 === strpos($field, 'HTTP/')) {
continue;
} elseif ($colpos === 0) { // HTTP/2 Field
}

// HTTP/2 field
if (0 === strpos($field, ':')) {
continue;
}

// end...
if ('' === $field) {
continue;
}

list($name, $value) = explode(':', $field, 2);
[$name, $value] = explode(':', $field, 2);

$response = $response->withAddedHeader(trim($name), trim($value));
$response = $response->withAddedHeader($name, ltrim($value));
}

return $response;
Expand Down
51 changes: 16 additions & 35 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,28 @@ public function testConstructor()

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

public function testSendRequests()
{
$requests = [];

$url = 'https://raw.githubusercontent.com';
$url .= '/sunrise-php/http-client-curl/dea2ea60d8d5b9f0839d8dba8cd714213c1c2b50/LICENSE';
$requests[] = (new RequestFactory)->createRequest('GET', $url);

$url = 'https://raw.githubusercontent.com';
$url .= '/sunrise-php/http-client-curl/b52d6cf88186101562ed93d9dbbb909ae82924d4/README.md';
$requests[] = (new RequestFactory)->createRequest('GET', $url);

$client = new Client(new ResponseFactory());
$requests = [];
$requests[] = (new RequestFactory)->createRequest('GET', 'https://www.php.net/');
$requests[] = (new RequestFactory)->createRequest('GET', 'https://www.php.net/');
$responses = $client->sendRequests(...$requests);

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

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

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

public function testClientException()
{
$message = 'foo';
$code = 1;
$previous = new RuntimeException('bar');
$previous = new RuntimeException();

$exception = new ClientException($message, $code, $previous);
$exception = new ClientException('foo', 42, $previous);
$this->assertInstanceOf(RuntimeException::class, $exception);
$this->assertInstanceOf(ClientExceptionInterface::class, $exception);

$this->assertSame($message, $exception->getMessage());
$this->assertSame($code, $exception->getCode());
$this->assertSame('foo', $exception->getMessage());
$this->assertSame(42, $exception->getCode());
$this->assertSame($previous, $exception->getPrevious());
}

public function testNetworkException()
{
$request = (new RequestFactory)->createRequest('GET', 'http://php.net/');
$message = 'foo';
$code = 1;
$previous = new RuntimeException('bar');
$previous = new RuntimeException();

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

$this->assertSame($request, $exception->getRequest());
$this->assertSame($message, $exception->getMessage());
$this->assertSame($code, $exception->getCode());
$this->assertSame('foo', $exception->getMessage());
$this->assertSame(42, $exception->getCode());
$this->assertSame($previous, $exception->getPrevious());
}

public function testRequestException()
{
$request = (new RequestFactory)->createRequest('GET', 'http://php.net/');
$message = 'foo';
$code = 1;
$previous = new RuntimeException('bar');
$previous = new RuntimeException();

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

$this->assertSame($request, $exception->getRequest());
$this->assertSame($message, $exception->getMessage());
$this->assertSame($code, $exception->getCode());
$this->assertSame('foo', $exception->getMessage());
$this->assertSame(42, $exception->getCode());
$this->assertSame($previous, $exception->getPrevious());
}
}

0 comments on commit c9e9e1b

Please sign in to comment.