You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
459 lines
15 KiB
459 lines
15 KiB
<?php
|
|
|
|
/**
|
|
* Slim Framework (https://slimframework.com)
|
|
*
|
|
* @license https://github.com/slimphp/Slim-Psr7/blob/master/LICENSE.md (MIT License)
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Slim\Tests\Psr7;
|
|
|
|
use InvalidArgumentException;
|
|
use PHPUnit\Framework\TestCase;
|
|
use ReflectionProperty;
|
|
use Slim\Psr7\Environment;
|
|
use Slim\Psr7\Factory\StreamFactory;
|
|
use Slim\Psr7\Factory\UriFactory;
|
|
use Slim\Psr7\Headers;
|
|
use Slim\Psr7\Request;
|
|
use Slim\Psr7\UploadedFile;
|
|
use Slim\Psr7\Uri;
|
|
|
|
use function property_exists;
|
|
use function sprintf;
|
|
|
|
class RequestTest extends TestCase
|
|
{
|
|
public function requestFactory($envData = []): Request
|
|
{
|
|
$env = Environment::mock($envData);
|
|
|
|
$uri = (new UriFactory())->createUri('https://example.com:443/foo/bar?abc=123');
|
|
$headers = Headers::createFromGlobals($env);
|
|
$cookies = [
|
|
'user' => 'john',
|
|
'id' => '123',
|
|
];
|
|
$serverParams = $env;
|
|
$body = (new StreamFactory())->createStream();
|
|
$uploadedFiles = UploadedFile::createFromGlobals($env);
|
|
$request = new Request('GET', $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles);
|
|
|
|
return $request;
|
|
}
|
|
|
|
public function testDisableSetter()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$request->foo = 'bar';
|
|
|
|
$this->assertFalse(property_exists($request, 'foo'));
|
|
}
|
|
|
|
public function testAddsHostHeaderFromUri()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$this->assertEquals('example.com', $request->getHeaderLine('Host'));
|
|
}
|
|
|
|
public function testGetMethod()
|
|
{
|
|
$this->assertEquals('GET', $this->requestFactory()->getMethod());
|
|
}
|
|
|
|
public function testWithMethod()
|
|
{
|
|
$request = $this->requestFactory()->withMethod('PUT');
|
|
|
|
$this->assertEquals('PUT', $request->getMethod());
|
|
}
|
|
|
|
public function testWithMethodCaseSensitive()
|
|
{
|
|
$request = $this->requestFactory()->withMethod('pOsT');
|
|
|
|
$this->assertEquals('pOsT', $request->getMethod());
|
|
}
|
|
|
|
public function testWithAllAllowedCharactersMethod()
|
|
{
|
|
$request = $this->requestFactory()->withMethod("!#$%&'*+.^_`|~09AZ-");
|
|
|
|
$this->assertEquals("!#$%&'*+.^_`|~09AZ-", $request->getMethod());
|
|
}
|
|
|
|
public function testWithMethodInvalid()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$this->requestFactory()->withMethod('B@R');
|
|
}
|
|
|
|
public function testCreateRequestWithInvalidMethodString()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$uri = (new UriFactory())->createUri('https://example.com:443/foo/bar?abc=123');
|
|
$headers = new Headers();
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
|
|
new Request('B@R', $uri, $headers, $cookies, $serverParams, $body);
|
|
}
|
|
|
|
public function testCreateRequestWithInvalidMethodOther()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$uri = (new UriFactory())->createUri('https://example.com:443/foo/bar?abc=123');
|
|
$headers = new Headers();
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
|
|
new Request(10, $uri, $headers, $cookies, $serverParams, $body);
|
|
}
|
|
|
|
public function testGetRequestTarget()
|
|
{
|
|
$this->assertEquals('/foo/bar?abc=123', $this->requestFactory()->getRequestTarget());
|
|
}
|
|
|
|
public function testGetRequestTargetAlreadySet()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$prop = new ReflectionProperty($request, 'requestTarget');
|
|
$prop->setAccessible(true);
|
|
$prop->setValue($request, '/foo/bar?abc=123');
|
|
|
|
$this->assertEquals('/foo/bar?abc=123', $request->getRequestTarget());
|
|
}
|
|
|
|
public function testGetRequestTargetIfNoUri()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$prop = new ReflectionProperty($request, 'uri');
|
|
$prop->setAccessible(true);
|
|
$prop->setValue($request, null);
|
|
|
|
$this->assertEquals('/', $request->getRequestTarget());
|
|
}
|
|
|
|
public function testWithRequestTarget()
|
|
{
|
|
$clone = $this->requestFactory()->withRequestTarget('/test?user=1');
|
|
|
|
$this->assertEquals('/test?user=1', $clone->getRequestTarget());
|
|
}
|
|
|
|
public function testWithRequestTargetThatHasSpaces()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$this->requestFactory()->withRequestTarget('/test/m ore/stuff?user=1');
|
|
}
|
|
|
|
public function testGetUri()
|
|
{
|
|
$uri = (new UriFactory())->createUri('https://example.com:443/foo/bar?abc=123');
|
|
$headers = new Headers();
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
$request = new Request('GET', $uri, $headers, $cookies, $serverParams, $body);
|
|
|
|
$this->assertSame($uri, $request->getUri());
|
|
}
|
|
|
|
public function testWithUri()
|
|
{
|
|
// Uris
|
|
$uri1 = (new UriFactory())->createUri('https://example.com:443/foo/bar?abc=123');
|
|
$uri2 = (new UriFactory())->createUri('https://example2.com:443/test?xyz=123');
|
|
|
|
// Request
|
|
$headers = new Headers();
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
$request = new Request('GET', $uri1, $headers, $cookies, $serverParams, $body);
|
|
$clone = $request->withUri($uri2);
|
|
|
|
$this->assertSame($uri2, $clone->getUri());
|
|
}
|
|
|
|
public function testWithUriPreservesHost()
|
|
{
|
|
// When `$preserveHost` is set to `true`, this method interacts with
|
|
// the Host header in the following ways:
|
|
|
|
// - If the Host header is missing or empty, and the new URI contains
|
|
// a host component, this method MUST update the Host header in the returned
|
|
// request.
|
|
$uri1 = (new UriFactory())->createUri('');
|
|
$uri2 = (new UriFactory())->createUri('http://example2.com/test');
|
|
|
|
// Request
|
|
$headers = new Headers();
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
$request = new Request('GET', $uri1, $headers, $cookies, $serverParams, $body);
|
|
|
|
$clone = $request->withUri($uri2, true);
|
|
$this->assertSame('example2.com', $clone->getHeaderLine('Host'));
|
|
|
|
// - If the Host header is missing or empty, and the new URI does not contain a
|
|
// host component, this method MUST NOT update the Host header in the returned
|
|
// request.
|
|
$uri3 = (new UriFactory())->createUri('');
|
|
|
|
$clone = $request->withUri($uri3, true);
|
|
$this->assertSame('', $clone->getHeaderLine('Host'));
|
|
|
|
// - If a Host header is present and non-empty, this method MUST NOT update
|
|
// the Host header in the returned request.
|
|
$request = $request->withHeader('Host', 'example.com');
|
|
$clone = $request->withUri($uri2, true);
|
|
$this->assertSame('example.com', $clone->getHeaderLine('Host'));
|
|
}
|
|
|
|
public function testGetCookieParams()
|
|
{
|
|
$shouldBe = [
|
|
'user' => 'john',
|
|
'id' => '123',
|
|
];
|
|
|
|
$this->assertEquals($shouldBe, $this->requestFactory()->getCookieParams());
|
|
}
|
|
|
|
public function testWithCookieParams()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$clone = $request->withCookieParams(['type' => 'framework']);
|
|
|
|
$this->assertEquals(['type' => 'framework'], $clone->getCookieParams());
|
|
}
|
|
|
|
public function testGetQueryParams()
|
|
{
|
|
$this->assertEquals(['abc' => '123'], $this->requestFactory()->getQueryParams());
|
|
}
|
|
|
|
public function testGetQueryParamsAlreadySet()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$prop = new ReflectionProperty($request, 'queryParams');
|
|
$prop->setAccessible(true);
|
|
$prop->setValue($request, ['foo' => 'bar']);
|
|
|
|
$this->assertEquals(['foo' => 'bar'], $request->getQueryParams());
|
|
}
|
|
|
|
public function testWithQueryParams()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$clone = $request->withQueryParams(['foo' => 'bar']);
|
|
$cloneUri = $clone->getUri();
|
|
|
|
$this->assertEquals('abc=123', $cloneUri->getQuery()); // <-- Unchanged
|
|
$this->assertEquals(['foo' => 'bar'], $clone->getQueryParams()); // <-- Changed
|
|
}
|
|
|
|
public function testWithQueryParamsEmptyArray()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$clone = $request->withQueryParams([]);
|
|
$cloneUri = $clone->getUri();
|
|
|
|
$this->assertEquals('abc=123', $cloneUri->getQuery()); // <-- Unchanged
|
|
$this->assertEquals([], $clone->getQueryParams()); // <-- Changed
|
|
}
|
|
|
|
public function testGetQueryParamsWithoutUri()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$prop = new ReflectionProperty($request, 'uri');
|
|
$prop->setAccessible(true);
|
|
$prop->setValue($request, null);
|
|
|
|
$this->assertEquals([], $request->getQueryParams());
|
|
}
|
|
|
|
public function testWithUploadedFiles()
|
|
{
|
|
$files = [new UploadedFile('foo.txt'), new UploadedFile('bar.txt')];
|
|
|
|
$request = $this->requestFactory();
|
|
$prevUploaded = $request->getUploadedFiles();
|
|
$clone = $request->withUploadedFiles($files);
|
|
|
|
$this->assertEquals($prevUploaded, $request->getUploadedFiles());
|
|
$this->assertEquals($files, $clone->getUploadedFiles());
|
|
}
|
|
|
|
public function testGetServerParams()
|
|
{
|
|
$mockEnv = Environment::mock(["HTTP_AUTHORIZATION" => "test"]);
|
|
$request = $this->requestFactory(["HTTP_AUTHORIZATION" => "test"]);
|
|
|
|
$serverParams = $request->getServerParams();
|
|
foreach ($serverParams as $key => $value) {
|
|
if ($key == 'REQUEST_TIME' || $key == 'REQUEST_TIME_FLOAT') {
|
|
$this->assertGreaterThanOrEqual(
|
|
$mockEnv[$key],
|
|
$value,
|
|
sprintf("%s value of %s was less than expected value of %s", $key, $value, $mockEnv[$key])
|
|
);
|
|
} else {
|
|
$this->assertEquals(
|
|
$mockEnv[$key],
|
|
$value,
|
|
sprintf("%s value of %s did not equal expected value of %s", $key, $value, $mockEnv[$key])
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function testGetAttributes()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$attrProp = new ReflectionProperty($request, 'attributes');
|
|
$attrProp->setAccessible(true);
|
|
$attrProp->setValue($request, ['foo' => 'bar']);
|
|
|
|
$this->assertEquals(['foo' => 'bar'], $request->getAttributes());
|
|
}
|
|
|
|
public function testGetAttribute()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$attrProp = new ReflectionProperty($request, 'attributes');
|
|
$attrProp->setAccessible(true);
|
|
$attrProp->setValue($request, ['foo' => 'bar']);
|
|
|
|
$this->assertEquals('bar', $request->getAttribute('foo'));
|
|
$this->assertNull($request->getAttribute('bar'));
|
|
$this->assertEquals(2, $request->getAttribute('bar', 2));
|
|
}
|
|
|
|
public function testWithAttribute()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$attrProp = new ReflectionProperty($request, 'attributes');
|
|
$attrProp->setAccessible(true);
|
|
$attrProp->setValue($request, ['foo' => 'bar']);
|
|
$clone = $request->withAttribute('test', '123');
|
|
|
|
$this->assertEquals('123', $clone->getAttribute('test'));
|
|
}
|
|
|
|
public function testWithoutAttribute()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$attrProp = new ReflectionProperty($request, 'attributes');
|
|
$attrProp->setAccessible(true);
|
|
$attrProp->setValue($request, ['foo' => 'bar']);
|
|
$clone = $request->withoutAttribute('foo');
|
|
|
|
$this->assertNull($clone->getAttribute('foo'));
|
|
}
|
|
|
|
public function testGetParsedBodyWhenAlreadyParsed()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$prop = new ReflectionProperty($request, 'parsedBody');
|
|
$prop->setAccessible(true);
|
|
$prop->setValue($request, ['foo' => 'bar']);
|
|
|
|
$this->assertEquals(['foo' => 'bar'], $request->getParsedBody());
|
|
}
|
|
|
|
public function testGetParsedBodyWhenBodyDoesNotExist()
|
|
{
|
|
$request = $this->requestFactory();
|
|
$prop = new ReflectionProperty($request, 'body');
|
|
$prop->setAccessible(true);
|
|
$prop->setValue($request, null);
|
|
|
|
$this->assertNull($request->getParsedBody());
|
|
}
|
|
|
|
public function testWithParsedBody()
|
|
{
|
|
$clone = $this->requestFactory()->withParsedBody(['xyz' => '123']);
|
|
|
|
$this->assertEquals(['xyz' => '123'], $clone->getParsedBody());
|
|
}
|
|
|
|
public function testWithParsedBodyEmptyArray()
|
|
{
|
|
$method = 'GET';
|
|
$uri = new Uri('https', 'example.com', 443, '/foo/bar', 'abc=123', '', '');
|
|
$headers = new Headers();
|
|
$headers->setHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf8');
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
$body->write('foo=bar');
|
|
$request = new Request($method, $uri, $headers, $cookies, $serverParams, $body);
|
|
|
|
$clone = $request->withParsedBody([]);
|
|
|
|
$this->assertEquals([], $clone->getParsedBody());
|
|
}
|
|
|
|
public function testWithParsedBodyNull()
|
|
{
|
|
$method = 'GET';
|
|
$uri = new Uri('https', 'example.com', 443, '/foo/bar', 'abc=123', '', '');
|
|
$headers = new Headers();
|
|
$headers->setHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf8');
|
|
$cookies = [];
|
|
$serverParams = [];
|
|
$body = (new StreamFactory())->createStream();
|
|
$body->write('foo=bar');
|
|
$request = new Request($method, $uri, $headers, $cookies, $serverParams, $body);
|
|
|
|
$clone = $request->withParsedBody(null);
|
|
|
|
$this->assertNull($clone->getParsedBody());
|
|
}
|
|
|
|
public function testGetParsedBodyReturnsNullWhenThereIsNoBodyData()
|
|
{
|
|
$request = $this->requestFactory(['REQUEST_METHOD' => 'POST']);
|
|
|
|
$this->assertNull($request->getParsedBody());
|
|
}
|
|
|
|
public function testGetParsedBodyReturnsNullWhenThereIsNoMediaTypeParserRegistered()
|
|
{
|
|
$request = $this->requestFactory([
|
|
'REQUEST_METHOD' => 'POST',
|
|
'CONTENT_TYPE' => 'text/csv',
|
|
]);
|
|
$request->getBody()->write('foo,bar,baz');
|
|
|
|
$this->assertNull($request->getParsedBody());
|
|
}
|
|
|
|
public function testWithParsedBodyInvalid()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$this->requestFactory()->withParsedBody(2);
|
|
}
|
|
|
|
public function testWithParsedBodyInvalidFalseValue()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
|
|
$this->requestFactory()->withParsedBody(false);
|
|
}
|
|
}
|