Skip to content

Commit

Permalink
Merge pull request #63 from jolicode/feat/remove-psr
Browse files Browse the repository at this point in the history
feat(http): remove dep on psr http, only rely on amp http client
  • Loading branch information
joelwurtz committed Apr 10, 2024
2 parents 3bcfefe + 67a0633 commit c318579
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 193 deletions.
15 changes: 7 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,24 @@
"require": {
"php": "^8.2",
"amphp/amp": "^3.0",
"amphp/http-client": "^v5.0.1",
"amphp/sync": "^2.0",
"bovigo/assert": "^7.0",
"symfony/console": "^4.4 || ^5.0 || ^6.0",
"symfony/finder": "^4.4 || ^5.0 || ^6.0"
},
"suggest": {
"amphp/http-client": "To use the web test case trait",
"nyholm/psr7": "To use the web test case trait"
"amphp/http-client": "To use the web test case trait"
},
"require-dev": {
"amphp/http-client": "v5.0.0-beta.11",
"friendsofphp/php-cs-fixer": "^v3.16.0",
"nyholm/psr7": "^1.8.0",
"php-http/client-common": "^2.4",
"php-http/message": "^1.3",
"amphp/http-client": "^5.0.1",
"friendsofphp/php-cs-fixer": "^3.16.0",
"phpstan/phpstan": "^1.10"
},
"conflict": {
"amphp/http-client": "<v5.0.0",
"amphp/http-client": "<5.0.1",
"amphp/byte-stream": "<2.1",
"amphp/http": "<2.1",
"symfony/options-resolver": "<4.4.30 || <5.3 >= 5.0"
},
"prefer-stable": true,
Expand Down
12 changes: 6 additions & 6 deletions src/Assert/AssertWebCaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@

namespace Asynit\Assert;

use Psr\Http\Message\ResponseInterface;
use Amp\Http\HttpResponse;

trait AssertWebCaseTrait
{
use AssertCaseTrait;

public function assertStatusCode($expectedStatus, ResponseInterface $response, $message = null)
public function assertStatusCode($expectedStatus, HttpResponse $response, $message = null)
{
$this->assertEquals($expectedStatus, $response->getStatusCode(), $message ?? 'Assert status code is equals to '.$expectedStatus);
$this->assertEquals($expectedStatus, $response->getStatus(), $message ?? 'Assert status code is equals to '.$expectedStatus);
}

public function assertContentType($expected, ResponseInterface $response, $message = null)
public function assertContentType($expected, HttpResponse $response, $message = null)
{
$contentType = $response->getHeaderLine('Content-Type');
$contentType = $response->getHeader('Content-Type');

$this->assertContains($expected, $contentType, $message ?? 'Assert content type is "'.$expected.'"');
}

public function assertHtml(ResponseInterface $response, $message = null)
public function assertHtml(HttpResponse $response, $message = null)
{
$this->assertContentType('text/html', $response, $message);
}
Expand Down
48 changes: 0 additions & 48 deletions src/HttpClient/AmpPsrHttpClient.php

This file was deleted.

70 changes: 11 additions & 59 deletions src/HttpClient/ApiResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,29 @@

namespace Asynit\HttpClient;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Amp\ByteStream\Payload;
use Amp\Http\Client\Response;
use Amp\Http\HttpResponse;

/**
* @implements \ArrayAccess<string, mixed>
*/
class ApiResponse implements \ArrayAccess, ResponseInterface
class ApiResponse extends HttpResponse implements \ArrayAccess
{
/**
* @var array<string, mixed>|null
*/
private array|null $data = null;

public function __construct(private ResponseInterface $response)
public function __construct(private readonly Response $response)
{
}

public function getStatusCode(): int
{
return $this->response->getStatusCode();
parent::__construct($response->getStatus(), $response->getReason());
}

private function ensureBodyIsRead(bool $associative = true): void
{
if (null === $this->data) {
$this->data = json_decode($this->response->getBody(), $associative, flags: JSON_THROW_ON_ERROR);
$this->data = json_decode($this->response->getBody()->read(), $associative, flags: JSON_THROW_ON_ERROR);
}
}

Expand Down Expand Up @@ -70,68 +67,23 @@ public function offsetUnset(mixed $offset): void
unset($this->data[$offset]);
}

public function getProtocolVersion()
{
return $this->response->getProtocolVersion();
}

public function withProtocolVersion(string $version): self
{
return new self($this->response->withProtocolVersion($version));
}

public function getHeaders()
public function getHeaders(): array
{
return $this->response->getHeaders();
}

public function hasHeader(string $name)
public function hasHeader(string $name): bool
{
return $this->response->hasHeader($name);
}

public function getHeader(string $name)
public function getHeader(string $name): null|string
{
return $this->response->getHeader($name);
}

public function getHeaderLine(string $name)
{
return $this->response->getHeaderLine($name);
}

public function withHeader(string $name, $value): self
{
return new self($this->response->withHeader($name, $value));
}

public function withAddedHeader(string $name, $value): self
{
return new self($this->response->withAddedHeader($name, $value));
}

public function withoutHeader(string $name): self
{
return new self($this->response->withoutHeader($name));
}

public function getBody()
public function getBody(): Payload
{
return $this->response->getBody();
}

public function withBody(StreamInterface $body): self
{
return new self($this->response->withBody($body));
}

public function withStatus(int $code, string $reasonPhrase = ''): self
{
return new self($this->response->withStatus($code, $reasonPhrase));
}

public function getReasonPhrase()
{
return $this->response->getReasonPhrase();
}
}
44 changes: 19 additions & 25 deletions src/HttpClient/HttpClientApiCaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Asynit\HttpClient;

use Psr\Http\Message\RequestInterface;
use Amp\Http\Client\Request;

trait HttpClientApiCaseTrait
{
Expand All @@ -13,54 +13,48 @@ protected function getApiContentType(): string
return 'application/json';
}

final protected function get(string $uri, array|null $json = null, array $headers = [], ?string $version = null): ApiResponse
final protected function get(string $uri, array|null $json = null, array $headers = []): ApiResponse
{
return new ApiResponse($this->sendRequest($this->createApiRequest('GET', $uri, $headers, $json, $version)));
return new ApiResponse($this->sendRequest($this->createApiRequest('GET', $uri, $headers, $json)));
}

final protected function post(string $uri, array|null $json = null, array $headers = [], ?string $version = null): ApiResponse
final protected function post(string $uri, array|null $json = null, array $headers = []): ApiResponse
{
return new ApiResponse($this->sendRequest($this->createApiRequest('POST', $uri, $headers, $json, $version)));
return new ApiResponse($this->sendRequest($this->createApiRequest('POST', $uri, $headers, $json)));
}

final protected function patch(string $uri, array|null $json = null, array $headers = [], ?string $version = null): ApiResponse
final protected function patch(string $uri, array|null $json = null, array $headers = []): ApiResponse
{
return new ApiResponse($this->sendRequest($this->createApiRequest('PATCH', $uri, $headers, $json, $version)));
return new ApiResponse($this->sendRequest($this->createApiRequest('PATCH', $uri, $headers, $json)));
}

final protected function put(string $uri, array|null $json = null, array $headers = [], ?string $version = null): ApiResponse
final protected function put(string $uri, array|null $json = null, array $headers = []): ApiResponse
{
return new ApiResponse($this->sendRequest($this->createApiRequest('PUT', $uri, $headers, $json, $version)));
return new ApiResponse($this->sendRequest($this->createApiRequest('PUT', $uri, $headers, $json)));
}

final protected function delete(string $uri, array|null $json = null, array $headers = [], ?string $version = null): ApiResponse
final protected function delete(string $uri, array|null $json = null, array $headers = []): ApiResponse
{
return new ApiResponse($this->sendRequest($this->createApiRequest('DELETE', $uri, $headers, $json, $version)));
return new ApiResponse($this->sendRequest($this->createApiRequest('DELETE', $uri, $headers, $json)));
}

final protected function options(string $uri, array|null $json = null, array $headers = [], ?string $version = null): ApiResponse
final protected function options(string $uri, array|null $json = null, array $headers = []): ApiResponse
{
return new ApiResponse($this->sendRequest($this->createApiRequest('OPTIONS', $uri, $headers, $json, $version)));
return new ApiResponse($this->sendRequest($this->createApiRequest('OPTIONS', $uri, $headers, $json)));
}

private function createApiRequest(string $method, string $uri, array $headers = [], array|null $json = null, ?string $version = null): RequestInterface
private function createApiRequest(string $method, string $uri, array $headers = [], array|null $json = null): Request
{
$request = $this->httpFactory->createRequest($method, $uri);
$request = $request->withHeader('Content-Type', $this->getApiContentType());
$request = $request->withHeader('Accept', $this->getApiContentType());
$request = new Request($uri, $method);
$request->addHeader('Content-Type', $this->getApiContentType());
$request->addHeader('Accept', $this->getApiContentType());

foreach ($headers as $name => $value) {
$request = $request->withHeader($name, $value);
$request->addHeader($name, $value);
}

if (null !== $json) {
$body = $this->httpFactory->createStream(json_encode($json, flags: JSON_THROW_ON_ERROR));

$request = $request->withBody($body);
}

if (null !== $version) {
$request = $request->withProtocolVersion($version);
$request->setBody(json_encode($json, flags: JSON_THROW_ON_ERROR));
}

return $request;
Expand Down
22 changes: 8 additions & 14 deletions src/HttpClient/HttpClientCaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,24 @@

use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\HttpClient;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\HttpResponse;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;
use Asynit\Assert\AssertWebCaseTrait;
use Asynit\Attribute\OnCreate;
use Nyholm\Psr7\Factory\Psr17Factory;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

trait HttpClientCaseTrait
{
use AssertWebCaseTrait;

private ClientInterface|null $httpClient = null;

private Psr17Factory|null $httpFactory = null;
private HttpClient|null $httpClient = null;

protected $allowSelfSignedCertificate = false;

protected function createHttpClient(bool $allowSelfSignedCertificate = false): ClientInterface
protected function createHttpClient(bool $allowSelfSignedCertificate = false): HttpClient
{
$tlsContext = new ClientTlsContext('');

Expand All @@ -37,24 +34,21 @@ protected function createHttpClient(bool $allowSelfSignedCertificate = false): C

$builder = new HttpClientBuilder();
$builder = $builder->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(null, $connectContext)));
$client = $builder->build();
$factory = new Psr17Factory();

return new AmpPsrHttpClient($client, $factory, $factory);
return $builder->build();
}

#[OnCreate]
final public function setUpHttpClient(): void
{
$this->httpClient = $this->createHttpClient($this->allowSelfSignedCertificate);
$this->httpFactory = new Psr17Factory();
}

/**
* Allow to test a rejection or a resolution of an async call.
*/
final protected function sendRequest(RequestInterface $request): ResponseInterface
final protected function sendRequest(Request $request): HttpResponse
{
return $this->httpClient->sendRequest($request);
return $this->httpClient->request($request);
}
}

0 comments on commit c318579

Please sign in to comment.