test_support-1.0.x-dev/tests/src/Traits/Http/MakesHttpRequests.php
tests/src/Traits/Http/MakesHttpRequests.php
<?php
namespace Drupal\Tests\test_support\Traits\Http;
use Drupal\Tests\test_support\Traits\Http\Response\TestResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
trait MakesHttpRequests
{
/** @var bool */
private $followRedirects = false;
/** @var array<string>|array<array<string>> */
private $headers = [];
/** @param array<mixed> $headers */
public function get(string $uri, array $headers = []): TestResponse
{
return $this->call('GET', $uri, [], [], [], $headers);
}
/** @param array<mixed> $headers */
public function getJson(string $uri, array $headers = []): TestResponse
{
return $this->json('GET', $uri, [], $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function post(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->call('POST', $uri, $data, [], [], $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function postJson(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->json('POST', $uri, $data, $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function put(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->call('PUT', $uri, $data, [], [], $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function putJson(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->json('PUT', $uri, $data, $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function patch(string $uri, array $data = [], array $headers = []): TestResponse
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = [];
return $this->call('PATCH', $uri, $data, $cookies, [], $server);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function patchJson(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->json('PATCH', $uri, $data, $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function options(string $uri, array $data = [], array $headers = []): TestResponse
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = [];
return $this->call('OPTIONS', $uri, $data, $cookies, [], $server);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function optionsJson(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->json('OPTIONS', $uri, $data, $headers);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function delete(string $uri, array $data = [], array $headers = []): TestResponse
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = [];
return $this->call('DELETE', $uri, $data, $cookies, [], $server);
}
/**
* @param array<mixed> $data
* @param array<mixed> $headers
*/
public function deleteJson(string $uri, array $data = [], array $headers = []): TestResponse
{
return $this->json('DELETE', $uri, $data, $headers);
}
public function ajax(): self
{
$this->headers = array_merge($this->headers, [
'X-Requested-With' => 'XMLHttpRequest',
]);
return $this;
}
public function asForm(): self
{
return $this->withHeader('Content-Type', 'application/x-www-form-urlencoded');
}
public function asJson(): self
{
return $this->withHeader('Content-Type', 'application/json');
}
/**
* @param null|resource|string $content
* @param array<mixed> $cookies
* @param array<mixed> $files
* @param array<mixed> $server
* @param resource|string|null $content
*/
public function json(string $method, string $uri, array $cookies = [], array $files = [], array $server = [], $content = null): TestResponse
{
$headers = array_merge([
'CONTENT_TYPE' => 'application/json',
'Accept' => 'application/json',
], $server);
if ($content !== null) {
$length = '';
if (is_resource($content)) {
$length = fstat($content)['size'] ?? '';
}
if (is_string($content)) {
$length = mb_strlen($content, '8bit');
}
$headers['CONTENT_LENGTH'] = $length;
}
return $this->call(
$method,
$uri,
[],
$cookies,
$files,
$headers,
$content
);
}
/**
* @param null|resource|string $content
* @param array<mixed> $parameters
* @param array<mixed> $cookies
* @param array<mixed> $files
* @param array<mixed> $server
* @param resource|string|null $content
*/
public function call(string $method, string $uri, array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null): TestResponse
{
$request = Request::create($uri, $method, $parameters, $cookies, $files, $server, $content);
$request->setSession($this->container->get('session'));
if ($this->headers) {
foreach ($this->headers as $header => $value) {
$request->headers->set($header, $value);
}
}
$httpKernel = $this->container->get('http_kernel');
$response = $httpKernel->handle($request);
$httpKernel->terminate($request, $response);
if ($this->followRedirects) {
$response = $this->followRedirects($response);
$this->followRedirects = false;
}
$kernel = $this->container->get('kernel');
/** @phpstan-ignore-next-line */
$kernel->invalidateContainer();
/** @phpstan-ignore-next-line */
$kernel->rebuildContainer();
return TestResponse::fromBaseResponse($response);
}
public function followingRedirects(): self
{
$this->followRedirects = true;
return $this;
}
public function from(string $url): self
{
return $this->withHeader('referer', $url);
}
/** @param array<string>|array<array<string>> $headers */
protected function withHeaders(array $headers): self
{
$this->headers = array_merge($this->headers, $headers);
return $this;
}
/** @param string|array<string> $value */
protected function withHeader(string $header, $value): self
{
$this->headers = array_merge($this->headers, [
$header => $value,
]);
return $this;
}
/**
* Transform headers array to array of $_SERVER vars with HTTP_* format.
*
* @param array<mixed> $headers
* @return array<mixed>
*/
protected function transformHeadersToServerVars(array $headers)
{
return collect(array_merge($this->headers, $headers))->mapWithKeys(function ($value, $name) {
$name = strtr(strtoupper($name), '-', '_');
return [
$this->formatServerHeaderKey($name) => $value,
];
})->all();
}
protected function formatServerHeaderKey(string $name): string
{
if (! str_starts_with($name, 'HTTP_') && $name !== 'CONTENT_TYPE' && $name !== 'REMOTE_ADDR') {
return 'HTTP_' . $name;
}
return $name;
}
private function followRedirects(Response $response): Response
{
$this->followRedirects = false;
while ($response->isRedirect()) {
$location = $response->headers->get('Location');
if ($location === null) {
break;
}
$response = $this->get($location);
}
return $response;
}
}
