Skip to content

Commit

Permalink
psr18
Browse files Browse the repository at this point in the history
  • Loading branch information
verfriemelt-dot-org committed Nov 21, 2024
1 parent 663ab87 commit 56afdf2
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 52 deletions.
46 changes: 26 additions & 20 deletions _/HttpClient/CurlHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@

namespace verfriemelt\wrapped\_\HttpClient;

use Psr\Http\Client\ClientInterface;
use RuntimeException;
use Override;

class CurlHttpClient implements HttpClientInterface
class CurlHttpClient implements HttpClientInterface, ClientInterface
{
use PsrAdapterTrait;

#[Override]
public function request(
string $uri,
string $method = 'get',
string $method = 'GET',
array $header = [],
?string $payload = null,
): HttpResponse {

$method = strtoupper($method);

if ($uri === '') {
throw new RuntimeException('empty uri passed');
}
Expand Down Expand Up @@ -43,33 +49,33 @@ public function request(
\curl_setopt(
$c,
\CURLOPT_HEADERFUNCTION,
static function ($curl, $header) use (&$responseHeaders) {
$len = \strlen((string) $header);
$header = \explode(':', (string) $header, 2);
static function ($curl, string $header) use (&$responseHeaders) {
$length = \strlen($header);
$header = \explode(':', $header, 2);

if (\count($header) < 2) {
return $len;
return $length;
}

$name = \strtolower(\trim($header[0]));
$responseHeaders[$name] = \trim($header[1]);
$responseHeaders[$header[0]] ??= [];
$responseHeaders[$header[0]][] = \trim($header[1]);

return $len;
return $length;
},
);

switch ($method) {
case 'get':
break;
case 'post':
\curl_setopt($c, \CURLOPT_POST, true);
if ($method === 'GET' && $payload !== null) {
throw new RuntimeException('get cannot have payloads');
}

if ($payload !== null) {
\curl_setopt($c, \CURLOPT_POSTFIELDS, $payload);
}
if ($method !== 'GET') {

// \curl_setopt($c, \CURLOPT_POST, true);

if ($payload !== null) {
\curl_setopt($c, \CURLOPT_POSTFIELDS, $payload);
}

break;
default: throw new RuntimeException('method not supported');
}

$response = \curl_exec($c);
Expand All @@ -78,7 +84,7 @@ static function ($curl, $header) use (&$responseHeaders) {
throw new RuntimeException('request failed');
}

if (\curl_errno($c) === 28) {
if (\curl_errno($c) === \CURLE_OPERATION_TIMEDOUT) {
throw new HttpRequestTimeoutException("timeout connecting to: $uri");
}

Expand Down
5 changes: 4 additions & 1 deletion _/HttpClient/DumpingHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
namespace verfriemelt\wrapped\_\HttpClient;

use Override;
use Psr\Http\Client\ClientInterface;

class DumpingHttpClient implements HttpClientInterface
class DumpingHttpClient implements HttpClientInterface, ClientInterface
{
use PsrAdapterTrait;

private int $requestNumber = 0;

public function __construct(
Expand Down
19 changes: 18 additions & 1 deletion _/HttpClient/HttpRequestException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@

namespace verfriemelt\wrapped\_\HttpClient;

use Psr\Http\Client\RequestExceptionInterface;
use Psr\Http\Message\RequestInterface;
use RuntimeException;
use Override;

class HttpRequestException extends RuntimeException {}
class HttpRequestException extends RuntimeException implements RequestExceptionInterface
{
private RequestInterface $request;

public function setRequest(RequestInterface $request): void
{
$this->request = $request;
}

#[Override]
public function getRequest(): RequestInterface
{
return $this->request;
}
}
2 changes: 1 addition & 1 deletion _/HttpClient/HttpResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
final readonly class HttpResponse
{
/**
* @param array<string,string> $header
* @param array<string,string[]> $header
*/
public function __construct(
public int $statusCode,
Expand Down
5 changes: 4 additions & 1 deletion _/HttpClient/MockHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
namespace verfriemelt\wrapped\_\HttpClient;

use Override;
use Psr\Http\Client\ClientInterface;
use RuntimeException;

final class MockHttpClient implements HttpClientInterface
final class MockHttpClient implements HttpClientInterface, ClientInterface
{
use PsrAdapterTrait;

/** @var HttpResponse[] */
private array $responses;

Expand Down
10 changes: 5 additions & 5 deletions _/HttpClient/Psr/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function getProtocolVersion(): string
}

#[Override]
public function withProtocolVersion(string $version): MessageInterface
public function withProtocolVersion(string $version): static
{
$instance = clone $this;
$instance->protocolVersion = $version;
Expand Down Expand Up @@ -75,7 +75,7 @@ public function getHeaderLine(string $name): string
}

#[Override]
public function withHeader(string $name, $value): MessageInterface
public function withHeader(string $name, $value): static
{
$instance = clone $this;

Expand All @@ -98,7 +98,7 @@ public function withHeader(string $name, $value): MessageInterface
}

#[Override]
public function withAddedHeader(string $name, $value): MessageInterface
public function withAddedHeader(string $name, $value): static
{
$instance = clone $this;

Expand All @@ -119,7 +119,7 @@ public function withAddedHeader(string $name, $value): MessageInterface
}

#[Override]
public function withoutHeader(string $name): MessageInterface
public function withoutHeader(string $name): static
{
$instance = clone $this;

Expand All @@ -140,7 +140,7 @@ public function getBody(): StreamInterface
}

#[Override]
public function withBody(StreamInterface $body): MessageInterface
public function withBody(StreamInterface $body): static
{
$instance = clone $this;
$instance->body = $body;
Expand Down
38 changes: 38 additions & 0 deletions _/HttpClient/PsrAdapterTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace verfriemelt\wrapped\_\HttpClient;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use verfriemelt\wrapped\_\HttpClient\Psr\Response;
use verfriemelt\wrapped\_\HttpClient\Psr\StreamFactory;

trait PsrAdapterTrait
{
public function sendRequest(RequestInterface $request): ResponseInterface
{
$header = \array_map(fn ($values) => \implode(',', $values), $request->getHeaders());

try {
$response = $this->request(
(string) $request->getUri(),
$request->getMethod(),
$header,
(string) $request->getBody(),
);
} catch (HttpRequestException $e) {
$e->setRequest($request);
throw $e;
}

$psrResponse = new Response(
$response->statusCode,
'',
$response->header,
);

return $psrResponse->withBody((new StreamFactory())->createStream($response->response));
}
}
5 changes: 4 additions & 1 deletion _/HttpClient/RetryableHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

use Closure;
use Override;
use Psr\Http\Client\ClientInterface;
use RuntimeException;

final class RetryableHttpClient implements HttpClientInterface
final class RetryableHttpClient implements HttpClientInterface, ClientInterface
{
use PsrAdapterTrait;

/** @var Closure(): void */
private Closure $callback;

Expand Down
10 changes: 6 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
"description": "for educational purposes only",
"license": "MIT",
"require": {
"php" : "^8.3",
"php": "^8.3",
"ext-curl": "*",
"ext-pdo": "*",
"psr/clock": "^1.0",
"psr/http-client": "^1.0.3",
"psr/http-factory": "^1.1",
"psr/http-message": "^2.0",
"ext-curl": "*",
"verfriemelt/pp": "^1.0"
},
"require-dev": {
"phpstan/phpstan": "^1.12.11",
"phpstan/phpstan-strict-rules": "^1.6.1",
"phpstan/phpstan-phpunit": "^1.4.1",
"phpunit/phpunit": "^10",
"phpunit/phpunit": "^10.5.38",
"rector/rector": "^1.2.10",
"friendsofphp/php-cs-fixer": "^3.64.0",
"tomasvotruba/type-coverage": "^1.0",
Expand All @@ -37,6 +38,7 @@
"config": {
"allow-plugins": {
"infection/extension-installer": false
}
},
"sort-packages": true
}
}
58 changes: 55 additions & 3 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 56afdf2

Please sign in to comment.