Skip to content
Permalink
8.x
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
<?php
namespace Illuminate\Foundation\Testing\Concerns;
use Illuminate\Contracts\Http\Kernel as HttpKernel;
use Illuminate\Cookie\CookieValuePrefix;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Testing\LoggedExceptionCollection;
use Illuminate\Testing\TestResponse;
use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyUploadedFile;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
trait MakesHttpRequests
{
/**
* Additional headers for the request.
*
* @var array
*/
protected $defaultHeaders = [];
/**
* Additional cookies for the request.
*
* @var array
*/
protected $defaultCookies = [];
/**
* Additional cookies will not be encrypted for the request.
*
* @var array
*/
protected $unencryptedCookies = [];
/**
* Additional server variables for the request.
*
* @var array
*/
protected $serverVariables = [];
/**
* Indicates whether redirects should be followed.
*
* @var bool
*/
protected $followRedirects = false;
/**
* Indicates whether cookies should be encrypted.
*
* @var bool
*/
protected $encryptCookies = true;
/**
* Indicated whether JSON requests should be performed "with credentials" (cookies).
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
*
* @var bool
*/
protected $withCredentials = false;
/**
* Define additional headers to be sent with the request.
*
* @param array $headers
* @return $this
*/
public function withHeaders(array $headers)
{
$this->defaultHeaders = array_merge($this->defaultHeaders, $headers);
return $this;
}
/**
* Add a header to be sent with the request.
*
* @param string $name
* @param string $value
* @return $this
*/
public function withHeader(string $name, string $value)
{
$this->defaultHeaders[$name] = $value;
return $this;
}
/**
* Add an authorization token for the request.
*
* @param string $token
* @param string $type
* @return $this
*/
public function withToken(string $token, string $type = 'Bearer')
{
return $this->withHeader('Authorization', $type.' '.$token);
}
/**
* Flush all the configured headers.
*
* @return $this
*/
public function flushHeaders()
{
$this->defaultHeaders = [];
return $this;
}
/**
* Define a set of server variables to be sent with the requests.
*
* @param array $server
* @return $this
*/
public function withServerVariables(array $server)
{
$this->serverVariables = $server;
return $this;
}
/**
* Disable middleware for the test.
*
* @param string|array|null $middleware
* @return $this
*/
public function withoutMiddleware($middleware = null)
{
if (is_null($middleware)) {
$this->app->instance('middleware.disable', true);
return $this;
}
foreach ((array) $middleware as $abstract) {
$this->app->instance($abstract, new class
{
public function handle($request, $next)
{
return $next($request);
}
});
}
return $this;
}
/**
* Enable the given middleware for the test.
*
* @param string|array|null $middleware
* @return $this
*/
public function withMiddleware($middleware = null)
{
if (is_null($middleware)) {
unset($this->app['middleware.disable']);
return $this;
}
foreach ((array) $middleware as $abstract) {
unset($this->app[$abstract]);
}
return $this;
}
/**
* Define additional cookies to be sent with the request.
*
* @param array $cookies
* @return $this
*/
public function withCookies(array $cookies)
{
$this->defaultCookies = array_merge($this->defaultCookies, $cookies);
return $this;
}
/**
* Add a cookie to be sent with the request.
*
* @param string $name
* @param string $value
* @return $this
*/
public function withCookie(string $name, string $value)
{
$this->defaultCookies[$name] = $value;
return $this;
}
/**
* Define additional cookies will not be encrypted before sending with the request.
*
* @param array $cookies
* @return $this
*/
public function withUnencryptedCookies(array $cookies)
{
$this->unencryptedCookies = array_merge($this->unencryptedCookies, $cookies);
return $this;
}
/**
* Add a cookie will not be encrypted before sending with the request.
*
* @param string $name
* @param string $value
* @return $this
*/
public function withUnencryptedCookie(string $name, string $value)
{
$this->unencryptedCookies[$name] = $value;
return $this;
}
/**
* Automatically follow any redirects returned from the response.
*
* @return $this
*/
public function followingRedirects()
{
$this->followRedirects = true;
return $this;
}
/**
* Include cookies and authorization headers for JSON requests.
*
* @return $this
*/
public function withCredentials()
{
$this->withCredentials = true;
return $this;
}
/**
* Disable automatic encryption of cookie values.
*
* @return $this
*/
public function disableCookieEncryption()
{
$this->encryptCookies = false;
return $this;
}
/**
* Set the referer header and previous URL session value in order to simulate a previous request.
*
* @param string $url
* @return $this
*/
public function from(string $url)
{
$this->app['session']->setPreviousUrl($url);
return $this->withHeader('referer', $url);
}
/**
* Visit the given URI with a GET request.
*
* @param string $uri
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function get($uri, array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = $this->prepareCookiesForRequest();
return $this->call('GET', $uri, [], $cookies, [], $server);
}
/**
* Visit the given URI with a GET request, expecting a JSON response.
*
* @param string $uri
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function getJson($uri, array $headers = [])
{
return $this->json('GET', $uri, [], $headers);
}
/**
* Visit the given URI with a POST request.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function post($uri, array $data = [], array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = $this->prepareCookiesForRequest();
return $this->call('POST', $uri, $data, $cookies, [], $server);
}
/**
* Visit the given URI with a POST request, expecting a JSON response.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function postJson($uri, array $data = [], array $headers = [])
{
return $this->json('POST', $uri, $data, $headers);
}
/**
* Visit the given URI with a PUT request.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function put($uri, array $data = [], array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = $this->prepareCookiesForRequest();
return $this->call('PUT', $uri, $data, $cookies, [], $server);
}
/**
* Visit the given URI with a PUT request, expecting a JSON response.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function putJson($uri, array $data = [], array $headers = [])
{
return $this->json('PUT', $uri, $data, $headers);
}
/**
* Visit the given URI with a PATCH request.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function patch($uri, array $data = [], array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = $this->prepareCookiesForRequest();
return $this->call('PATCH', $uri, $data, $cookies, [], $server);
}
/**
* Visit the given URI with a PATCH request, expecting a JSON response.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function patchJson($uri, array $data = [], array $headers = [])
{
return $this->json('PATCH', $uri, $data, $headers);
}
/**
* Visit the given URI with a DELETE request.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function delete($uri, array $data = [], array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = $this->prepareCookiesForRequest();
return $this->call('DELETE', $uri, $data, $cookies, [], $server);
}
/**
* Visit the given URI with a DELETE request, expecting a JSON response.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function deleteJson($uri, array $data = [], array $headers = [])
{
return $this->json('DELETE', $uri, $data, $headers);
}
/**
* Visit the given URI with an OPTIONS request.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function options($uri, array $data = [], array $headers = [])
{
$server = $this->transformHeadersToServerVars($headers);
$cookies = $this->prepareCookiesForRequest();
return $this->call('OPTIONS', $uri, $data, $cookies, [], $server);
}
/**
* Visit the given URI with an OPTIONS request, expecting a JSON response.
*
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function optionsJson($uri, array $data = [], array $headers = [])
{
return $this->json('OPTIONS', $uri, $data, $headers);
}
/**
* Call the given URI with a JSON request.
*
* @param string $method
* @param string $uri
* @param array $data
* @param array $headers
* @return \Illuminate\Testing\TestResponse
*/
public function json($method, $uri, array $data = [], array $headers = [])
{
$files = $this->extractFilesFromDataArray($data);
$content = json_encode($data);
$headers = array_merge([
'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
'CONTENT_TYPE' => 'application/json',
'Accept' => 'application/json',
], $headers);
return $this->call(
$method,
$uri,
[],
$this->prepareCookiesForJsonRequest(),
$files,
$this->transformHeadersToServerVars($headers),
$content
);
}
/**
* Call the given URI and return the Response.
*
* @param string $method
* @param string $uri
* @param array $parameters
* @param array $cookies
* @param array $files
* @param array $server
* @param string|null $content
* @return \Illuminate\Testing\TestResponse
*/
public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
{
$kernel = $this->app->make(HttpKernel::class);
$files = array_merge($files, $this->extractFilesFromDataArray($parameters));
$symfonyRequest = SymfonyRequest::create(
$this->prepareUrlForRequest($uri), $method, $parameters,
$cookies, $files, array_replace($this->serverVariables, $server), $content
);
$response = $kernel->handle(
$request = Request::createFromBase($symfonyRequest)
);
$kernel->terminate($request, $response);
if ($this->followRedirects) {
$response = $this->followRedirects($response);
}
return $this->createTestResponse($response);
}
/**
* Turn the given URI into a fully qualified URL.
*
* @param string $uri
* @return string
*/
protected function prepareUrlForRequest($uri)
{
if (Str::startsWith($uri, '/')) {
$uri = substr($uri, 1);
}
return trim(url($uri), '/');
}
/**
* Transform headers array to array of $_SERVER vars with HTTP_* format.
*
* @param array $headers
* @return array
*/
protected function transformHeadersToServerVars(array $headers)
{
return collect(array_merge($this->defaultHeaders, $headers))->mapWithKeys(function ($value, $name) {
$name = strtr(strtoupper($name), '-', '_');
return [$this->formatServerHeaderKey($name) => $value];
})->all();
}
/**
* Format the header name for the server array.
*
* @param string $name
* @return string
*/
protected function formatServerHeaderKey($name)
{
if (! Str::startsWith($name, 'HTTP_') && $name !== 'CONTENT_TYPE' && $name !== 'REMOTE_ADDR') {
return 'HTTP_'.$name;
}
return $name;
}
/**
* Extract the file uploads from the given data array.
*
* @param array $data
* @return array
*/
protected function extractFilesFromDataArray(&$data)
{
$files = [];
foreach ($data as $key => $value) {
if ($value instanceof SymfonyUploadedFile) {
$files[$key] = $value;
unset($data[$key]);
}
if (is_array($value)) {
$files[$key] = $this->extractFilesFromDataArray($value);
$data[$key] = $value;
}
}
return $files;
}
/**
* If enabled, encrypt cookie values for request.
*
* @return array
*/
protected function prepareCookiesForRequest()
{
if (! $this->encryptCookies) {
return array_merge($this->defaultCookies, $this->unencryptedCookies);
}
return collect($this->defaultCookies)->map(function ($value, $key) {
return encrypt(CookieValuePrefix::create($key, app('encrypter')->getKey()).$value, false);
})->merge($this->unencryptedCookies)->all();
}
/**
* If enabled, add cookies for JSON requests.
*
* @return array
*/
protected function prepareCookiesForJsonRequest()
{
return $this->withCredentials ? $this->prepareCookiesForRequest() : [];
}
/**
* Follow a redirect chain until a non-redirect is received.
*
* @param \Illuminate\Http\Response $response
* @return \Illuminate\Http\Response|\Illuminate\Testing\TestResponse
*/
protected function followRedirects($response)
{
$this->followRedirects = false;
while ($response->isRedirect()) {
$response = $this->get($response->headers->get('Location'));
}
return $response;
}
/**
* Create the test response instance from the given response.
*
* @param \Illuminate\Http\Response $response
* @return \Illuminate\Testing\TestResponse
*/
protected function createTestResponse($response)
{
return tap(TestResponse::fromBaseResponse($response), function ($response) {
$response->withExceptions(
$this->app->bound(LoggedExceptionCollection::class)
? $this->app->make(LoggedExceptionCollection::class)
: new LoggedExceptionCollection
);
});
}
}