Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 01d2e35

Browse files
GaryPEGEOTfabpot
authored andcommitted
[HttpClient] Add an HAR response factory for testing
1 parent d0c73cc commit 01d2e35

File tree

6 files changed

+1117
-0
lines changed

6 files changed

+1117
-0
lines changed

src/Symfony/Component/HttpClient/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Remove implementing `Http\Message\RequestFactory` from `HttplugClient`
8+
* Add `HarFileResponseFactory` testing utility, allow to replay responses from `.har` files
89

910
6.4
1011
---
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpClient\Test;
13+
14+
use Symfony\Component\HttpClient\Exception\TransportException;
15+
use Symfony\Component\HttpClient\Response\MockResponse;
16+
use Symfony\Contracts\HttpClient\ResponseInterface;
17+
18+
/**
19+
* See: https://w3c.github.io/web-performance/specs/HAR/Overview.html.
20+
*
21+
* @author Gary PEGEOT <[email protected]>
22+
*/
23+
class HarFileResponseFactory
24+
{
25+
public function __construct(private string $archiveFile)
26+
{
27+
}
28+
29+
public function setArchiveFile(string $archiveFile): void
30+
{
31+
$this->archiveFile = $archiveFile;
32+
}
33+
34+
public function __invoke(string $method, string $url, array $options): ResponseInterface
35+
{
36+
if (!is_file($this->archiveFile)) {
37+
throw new \InvalidArgumentException(sprintf('Invalid file path provided: "%s".', $this->archiveFile));
38+
}
39+
40+
$json = json_decode(json: file_get_contents($this->archiveFile), associative: true, flags: \JSON_THROW_ON_ERROR);
41+
42+
foreach ($json['log']['entries'] as $entry) {
43+
/**
44+
* @var array{status: int, headers: array, content: array} $response
45+
* @var array{method: string, url: string, postData: array} $request
46+
*/
47+
['response' => $response, 'request' => $request, 'startedDateTime' => $startedDateTime] = $entry;
48+
49+
$body = $this->getContent($response['content']);
50+
$entryMethod = $request['method'];
51+
$entryUrl = $request['url'];
52+
$requestBody = $options['body'] ?? null;
53+
54+
if ($method !== $entryMethod || $url !== $entryUrl) {
55+
continue;
56+
}
57+
58+
if (null !== $requestBody && $requestBody !== $this->getContent($request['postData'] ?? [])) {
59+
continue;
60+
}
61+
62+
$info = [
63+
'http_code' => $response['status'],
64+
'http_method' => $entryMethod,
65+
'response_headers' => [],
66+
'start_time' => strtotime($startedDateTime),
67+
'url' => $entryUrl,
68+
];
69+
70+
/** @var array{name: string, value: string} $header */
71+
foreach ($response['headers'] as $header) {
72+
['name' => $name, 'value' => $value] = $header;
73+
74+
$info['response_headers'][$name][] = $value;
75+
}
76+
77+
return new MockResponse($body, $info);
78+
}
79+
80+
throw new TransportException(sprintf('File "%s" does not contain a response for HTTP request "%s" "%s".', $this->archiveFile, $method, $url));
81+
}
82+
83+
/**
84+
* @param array{text: string, encoding: string} $content
85+
*/
86+
private function getContent(array $content): string
87+
{
88+
$text = $content['text'] ?? '';
89+
$encoding = $content['encoding'] ?? null;
90+
91+
return match ($encoding) {
92+
'base64' => base64_decode($text),
93+
null => $text,
94+
default => throw new \InvalidArgumentException(sprintf('Unsupported encoding "%s", currently only base64 is supported.', $encoding)),
95+
};
96+
}
97+
}

0 commit comments

Comments
 (0)