Skip to content

Commit

Permalink
Merge pull request #447 from php-http/1-to-2
Browse files Browse the repository at this point in the history
1 to 2
  • Loading branch information
dbu committed Feb 26, 2024
2 parents 8d796dd + 0f11377 commit 710ae3a
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 279 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/continuous-integration.yml
Expand Up @@ -43,6 +43,9 @@ jobs:
- dependencies: "php-http/guzzle7-adapter"
php-version: "8.2"
symfony-deprecations-helper: "weak"
- dependencies: "php-http/guzzle7-adapter"
php-version: "8.3"
symfony-deprecations-helper: "weak"

# Test with httplug 2.x clients
- dependencies: "php-http/guzzle7-adapter php-http/curl-client:^2.0.0 php-http/vcr-plugin:^1.0@dev php-http/socket-client:^2.0"
Expand All @@ -68,6 +71,10 @@ jobs:
symfony-require: "6.3.*"
php-version: "8.2"
symfony-deprecations-helper: "weak"
- dependencies: "php-http/guzzle7-adapter symfony/http-client:^6.0"
symfony-require: "6.4.*"
php-version: "8.1"
symfony-deprecations-helper: "weak"

steps:
- name: "Checkout"
Expand All @@ -86,8 +93,10 @@ jobs:
run: "composer config minimum-stability stable"
if: "${{ matrix.stability == 'stable' }}"

- name: "Install dependencies"
run: "composer require --no-progress --no-scripts --no-plugins symfony/flex ${{ matrix.dependencies }}"
- name: "Add dependencies and enable flex"
run: |
composer require --no-update symfony/flex ${{ matrix.dependencies }}
composer config --no-plugins allow-plugins.symfony/flex true
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -19,6 +19,10 @@ The change log describes what is "Added", "Removed", "Changed" or "Fixed" betwee

# Version 1

# 1.32.0 - 2023-12-06

- Added support for Symfony 7

# 1.31.0 - 2023-11-06

- Added configuration for the `header` authentication plugin (#437).
Expand Down
32 changes: 16 additions & 16 deletions composer.json
Expand Up @@ -31,15 +31,15 @@
"php-http/discovery": "^1.14",
"php-http/httplug": "^2.0",
"php-http/logger-plugin": "^1.1",
"php-http/message": "^1.9",
"php-http/message": "^1.13",
"php-http/stopwatch-plugin": "^1.2",
"psr/http-factory-implementation": "^1.0",
"psr/http-message": "^1.0 || ^2.0",
"symfony/config": "^5.4 || ^6.0",
"symfony/dependency-injection": "^5.4 || ^6.0",
"symfony/event-dispatcher": "^5.4 || ^6.0",
"symfony/http-kernel": "^5.4 || ^6.0",
"symfony/options-resolver": "^5.4 || ^6.0"
"symfony/config": "^5.4 || ^6.0 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
"symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
"symfony/options-resolver": "^5.4 || ^6.0 || ^7.0"
},
"conflict": {
"php-http/guzzle6-adapter": "<1.1",
Expand All @@ -51,21 +51,21 @@
},
"require-dev": {
"guzzlehttp/psr7": "^1.7 || ^2.0",
"matthiasnoback/symfony-dependency-injection-test": "^4.0",
"matthiasnoback/symfony-dependency-injection-test": "^4.0 || ^5.0",
"nyholm/nsa": "^1.1",
"nyholm/psr7": "^1.2.1",
"php-http/cache-plugin": "^1.7",
"php-http/mock-client": "^1.2",
"php-http/promise": "^1.0",
"symfony/browser-kit": "^5.4 || ^6.0",
"symfony/cache": "^5.4 || ^6.0",
"symfony/dom-crawler": "^5.4 || ^6.0",
"symfony/framework-bundle": "^5.4 || ^6.0",
"symfony/http-foundation": "^5.4 || ^6.0",
"symfony/phpunit-bridge": "^5.4 || ^6.0",
"symfony/stopwatch": "^5.4 || ^6.0",
"symfony/twig-bundle": "^5.4 || ^6.0",
"symfony/web-profiler-bundle": "^5.4 || ^6.0",
"symfony/browser-kit": "^5.4 || ^6.0 || ^7.0",
"symfony/cache": "^5.4 || ^6.0 || ^7.0",
"symfony/dom-crawler": "^5.4 || ^6.0 || ^7.0",
"symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0",
"symfony/http-foundation": "^5.4 || ^6.0 || ^7.0",
"symfony/phpunit-bridge": "^7.0.3",
"symfony/stopwatch": "^5.4 || ^6.0 || ^7.0",
"symfony/twig-bundle": "^5.4 || ^6.0 || ^7.0",
"symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0",
"twig/twig": "^1.41 || ^2.10 || ^3.0"
},
"suggest": {
Expand Down
7 changes: 2 additions & 5 deletions src/Collector/Formatter.php
Expand Up @@ -33,7 +33,7 @@ class Formatter implements MessageFormatter
*/
private $curlFormatter;

public function __construct(MessageFormatter $formatter, CurlCommandFormatter $curlFormatter)
public function __construct(MessageFormatter $formatter, MessageFormatter $curlFormatter)
{
$this->formatter = $formatter;
$this->curlFormatter = $curlFormatter;
Expand All @@ -47,7 +47,7 @@ public function __construct(MessageFormatter $formatter, CurlCommandFormatter $c
public function formatException(\Throwable $exception)
{
if ($exception instanceof HttpException) {
return $this->formatter->formatResponse($exception->getResponse());
return $this->formatter->formatResponseForRequest($exception->getResponse(), $exception->getRequest());
}

if ($exception instanceof TransferException || $exception instanceof NetworkExceptionInterface) {
Expand All @@ -74,9 +74,6 @@ public function formatResponseForRequest(ResponseInterface $response, RequestInt
return $this->formatter->formatResponse($response);
}

/**
* {@inheritdoc}
*/
public function formatResponse(ResponseInterface $response)
{
return $this->formatter->formatResponse($response);
Expand Down
30 changes: 9 additions & 21 deletions src/Collector/ProfileClient.php
Expand Up @@ -69,9 +69,6 @@ public function __construct($client, Collector $collector, Formatter $formatter,
$this->stopwatch = $stopwatch;
}

/**
* {@inheritdoc}
*/
public function sendAsyncRequest(RequestInterface $request)
{
$activateStack = true;
Expand All @@ -88,8 +85,8 @@ public function sendAsyncRequest(RequestInterface $request)
$this->collectRequestInformations($request, $stack);
$event = $this->stopwatch->start($this->getStopwatchEventName($request), self::STOPWATCH_CATEGORY);

$onFulfilled = function (ResponseInterface $response) use ($event, $stack) {
$this->collectResponseInformations($response, $event, $stack);
$onFulfilled = function (ResponseInterface $response) use ($request, $event, $stack) {
$this->collectResponseInformations($request, $response, $event, $stack);
$event->stop();

return $response;
Expand Down Expand Up @@ -133,13 +130,9 @@ protected function doSendRequest(RequestInterface $request)

try {
$response = $this->client->sendRequest($request);
$this->collectResponseInformations($response, $event, $stack);
$this->collectResponseInformations($request, $response, $event, $stack);

return $response;
} catch (\Exception $e) {
$this->collectExceptionInformations($e, $event, $stack);

throw $e;
} catch (\Throwable $e) {
$this->collectExceptionInformations($e, $event, $stack);

Expand All @@ -149,7 +142,7 @@ protected function doSendRequest(RequestInterface $request)
}
}

private function collectRequestInformations(RequestInterface $request, Stack $stack)
private function collectRequestInformations(RequestInterface $request, Stack $stack): void
{
$uri = $request->getUri();
$stack->setRequestTarget($request->getRequestTarget());
Expand All @@ -161,29 +154,24 @@ private function collectRequestInformations(RequestInterface $request, Stack $st
$stack->setCurlCommand($this->formatter->formatAsCurlCommand($request));
}

private function collectResponseInformations(ResponseInterface $response, StopwatchEvent $event, Stack $stack)
private function collectResponseInformations(RequestInterface $request, ResponseInterface $response, StopwatchEvent $event, Stack $stack): void
{
$stack->setDuration($event->getDuration());
$stack->setResponseCode($response->getStatusCode());
$stack->setClientResponse($this->formatter->formatResponse($response));
$stack->setClientResponse($this->formatter->formatResponseForRequest($response, $request));
}

private function collectExceptionInformations(\Throwable $exception, StopwatchEvent $event, Stack $stack)
private function collectExceptionInformations(\Throwable $exception, StopwatchEvent $event, Stack $stack): void
{
if ($exception instanceof HttpException) {
$this->collectResponseInformations($exception->getResponse(), $event, $stack);
$this->collectResponseInformations($exception->getRequest(), $exception->getResponse(), $event, $stack);
}

$stack->setDuration($event->getDuration());
$stack->setClientException($this->formatter->formatException($exception));
}

/**
* Generates the event name.
*
* @return string
*/
private function getStopwatchEventName(RequestInterface $request)
private function getStopwatchEventName(RequestInterface $request): string
{
$name = sprintf('%s %s', $request->getMethod(), $request->getUri());

Expand Down
23 changes: 10 additions & 13 deletions src/Collector/ProfilePlugin.php
Expand Up @@ -48,6 +48,9 @@ protected function doHandleRequest(RequestInterface $request, callable $next, ca
$profile = new Profile(get_class($this->plugin));

$stack = $this->collector->getActiveStack();
if (null === $stack) {
throw new \LogicException('No active stack');
}
$stack->addProfile($profile);

// wrap the next callback to profile the plugin request changes
Expand Down Expand Up @@ -83,39 +86,33 @@ protected function doHandleRequest(RequestInterface $request, callable $next, ca
});
}

/**
* @param Stack $stack
*/
private function onException(
RequestInterface $request,
Profile $profile,
Exception $exception,
Stack $stack = null
) {
Stack $stack
): void {
$profile->setFailed(true);
$profile->setResponse($this->formatter->formatException($exception));
$this->collectRequestInformation($request, $stack);
}

private function onOutgoingRequest(RequestInterface $request, Profile $profile)
private function onOutgoingRequest(RequestInterface $request, Profile $profile): void
{
$profile->setRequest($this->formatter->formatRequest($request));
}

/**
* @param Stack $stack
*/
private function onOutgoingResponse(ResponseInterface $response, Profile $profile, RequestInterface $request, Stack $stack = null)
private function onOutgoingResponse(ResponseInterface $response, Profile $profile, RequestInterface $request, Stack $stack): void
{
$profile->setResponse($this->formatter->formatResponse($response));
$profile->setResponse($this->formatter->formatResponseForRequest($response, $request));
$this->collectRequestInformation($request, $stack);
}

/**
* Collect request information when not already done by the HTTP client. This happens when using the CachePlugin
* and the cache is hit without re-validation.
*/
private function collectRequestInformation(RequestInterface $request, Stack $stack = null)
private function collectRequestInformation(RequestInterface $request, Stack $stack): void
{
$uri = $request->getUri();
if (empty($stack->getRequestTarget())) {
Expand All @@ -127,7 +124,7 @@ private function collectRequestInformation(RequestInterface $request, Stack $sta
if (empty($stack->getRequestScheme())) {
$stack->setRequestScheme($uri->getScheme());
}
if (empty($stack->getRequestPort())) {
if (null === $stack->getRequestPort()) {
$stack->setRequestPort($uri->getPort());
}
if (empty($stack->getRequestHost())) {
Expand Down
4 changes: 2 additions & 2 deletions src/Collector/StackPlugin.php
Expand Up @@ -53,8 +53,8 @@ protected function doHandleRequest(RequestInterface $request, callable $next, ca
$this->collector->addStack($stack);
$this->collector->activateStack($stack);

$onFulfilled = function (ResponseInterface $response) use ($stack) {
$stack->setResponse($this->formatter->formatResponse($response));
$onFulfilled = function (ResponseInterface $response) use ($stack, $request) {
$stack->setResponse($this->formatter->formatResponseForRequest($response, $request));

return $response;
};
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/ClientFactory/CurlFactoryTest.php
Expand Up @@ -22,8 +22,8 @@ public function testCreateClient(): void
}

$factory = new CurlFactory(
$this->getMockBuilder(ResponseFactoryInterface::class)->getMock(),
$this->getMockBuilder(StreamFactoryInterface::class)->getMock()
$this->createMock(ResponseFactoryInterface::class),
$this->createMock(StreamFactoryInterface::class)
);
$client = $factory->createClient();

Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/ClientFactory/SymfonyFactoryTest.php
Expand Up @@ -22,8 +22,8 @@ public function testCreateClient(): void
}

$factory = new SymfonyFactory(
$this->getMockBuilder(ResponseFactoryInterface::class)->getMock(),
$this->getMockBuilder(StreamFactoryInterface::class)->getMock()
$this->createMock(ResponseFactoryInterface::class),
$this->createMock(StreamFactoryInterface::class)
);
$client = $factory->createClient();

Expand Down
40 changes: 32 additions & 8 deletions tests/Unit/Collector/FormatterTest.php
Expand Up @@ -11,18 +11,19 @@
use Http\HttplugBundle\Collector\Formatter;
use Http\Message\Formatter as MessageFormatter;
use Http\Message\Formatter\CurlCommandFormatter;
use Http\Message\Formatter\SimpleFormatter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class FormatterTest extends TestCase
{
/**
* @var MessageFormatter|MockObject
* @var MessageFormatter&MockObject
*/
private $formatter;

/**
* @var CurlCommandFormatter|MockObject
* @var CurlCommandFormatter&MockObject
*/
private $curlFormatter;

Expand All @@ -33,8 +34,8 @@ class FormatterTest extends TestCase

public function setUp(): void
{
$this->formatter = $this->getMockBuilder(MessageFormatter::class)->getMock();
$this->curlFormatter = $this->getMockBuilder(CurlCommandFormatter::class)->getMock();
$this->formatter = $this->createMock(MessageFormatter::class);
$this->curlFormatter = $this->createMock(CurlCommandFormatter::class);

$this->subject = new Formatter($this->formatter, $this->curlFormatter);
}
Expand All @@ -52,6 +53,26 @@ public function testFormatRequest(): void
$this->subject->formatRequest($request);
}

public function testFormatResponseForRequest(): void
{
$formatter = $this->createMock(SimpleFormatter::class);
$subject = new Formatter($formatter, $this->curlFormatter);

$response = new Response();
$request = new Request('GET', '/');

$formatter
->expects($this->once())
->method('formatResponseForRequest')
->with($this->identicalTo($response), $this->identicalTo($request))
;

$subject->formatResponseForRequest($response, $request);
}

/**
* @group legacy
*/
public function testFormatResponse(): void
{
$response = new Response();
Expand All @@ -67,18 +88,21 @@ public function testFormatResponse(): void

public function testFormatHttpException(): void
{
$formatter = $this->createMock(SimpleFormatter::class);
$subject = new Formatter($formatter, $this->curlFormatter);

$request = new Request('GET', '/');
$response = new Response();
$exception = new HttpException('', $request, $response);

$this->formatter
$formatter
->expects($this->once())
->method('formatResponse')
->with($this->identicalTo($response))
->method('formatResponseForRequest')
->with($this->identicalTo($response), $this->identicalTo($request))
->willReturn('FormattedException')
;

$this->assertEquals('FormattedException', $this->subject->formatException($exception));
$this->assertEquals('FormattedException', $subject->formatException($exception));
}

public function testFormatTransferException(): void
Expand Down

0 comments on commit 710ae3a

Please sign in to comment.