Files
yii2/tests/framework/web/RequestTest.php
yyxx9988 46bf3c410a Add yii\web\Request::getOrigin() method that returns HTTP_ORIGIN of current CORS request
>The Origin request header indicates where a fetch originates from. It doesn't include any path information, but only the server name. It is sent with CORS requests, as well as with POST requests. It is similar to the Referer header, but, unlike this header, it doesn't disclose the whole path.

From https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin

Working code samples

```php
<?php

// We'll be granting access to only the arunranga.com domain
// which we think is safe to access this resource as application/xml

if($_SERVER['HTTP_ORIGIN'] == "http://arunranga.com") {
    header('Access-Control-Allow-Origin: http://arunranga.com');
    header('Content-type: application/xml');
    readfile('arunerDotNetResource.xml');
} else {
  header('Content-Type: text/html');
  echo "<html>";
  echo "<head>";
  echo "   <title>Another Resource</title>";
  echo "</head>";
  echo "<body>",
       "<p>This resource behaves two-fold:";
  echo "<ul>",
         "<li>If accessed from <code>http://arunranga.com</code> it returns an XML document</li>";
  echo   "<li>If accessed from any other origin including from simply typing in the URL into the browser's address bar,";
  echo   "you get this HTML document</li>",
       "</ul>",
     "</body>",
   "</html>";
}
?>
```
See https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control for more info.

close #13835
2017-07-12 11:10:21 +02:00

307 lines
10 KiB
PHP

<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\web;
use yii\web\Request;
use yiiunit\TestCase;
/**
* @group web
*/
class RequestTest extends TestCase
{
public function testParseAcceptHeader()
{
$request = new Request();
$this->assertEquals([], $request->parseAcceptHeader(' '));
$this->assertEquals([
'audio/basic' => ['q' => 1],
'audio/*' => ['q' => 0.2],
], $request->parseAcceptHeader('audio/*; q=0.2, audio/basic'));
$this->assertEquals([
'application/json' => ['q' => 1, 'version' => '1.0'],
'application/xml' => ['q' => 1, 'version' => '2.0', 'x'],
'text/x-c' => ['q' => 1],
'text/x-dvi' => ['q' => 0.8],
'text/plain' => ['q' => 0.5],
], $request->parseAcceptHeader('text/plain; q=0.5,
application/json; version=1.0,
application/xml; version=2.0; x,
text/x-dvi; q=0.8, text/x-c'));
}
public function testPrefferedLanguage()
{
$this->mockApplication([
'language' => 'en',
]);
$request = new Request();
$request->acceptableLanguages = [];
$this->assertEquals('en', $request->getPreferredLanguage());
$request = new Request();
$request->acceptableLanguages = ['de'];
$this->assertEquals('en', $request->getPreferredLanguage());
$request = new Request();
$request->acceptableLanguages = ['en-us', 'de', 'ru-RU'];
$this->assertEquals('en', $request->getPreferredLanguage(['en']));
$request = new Request();
$request->acceptableLanguages = ['en-us', 'de', 'ru-RU'];
$this->assertEquals('de', $request->getPreferredLanguage(['ru', 'de']));
$this->assertEquals('de-DE', $request->getPreferredLanguage(['ru', 'de-DE']));
$request = new Request();
$request->acceptableLanguages = ['en-us', 'de', 'ru-RU'];
$this->assertEquals('de', $request->getPreferredLanguage(['de', 'ru']));
$request = new Request();
$request->acceptableLanguages = ['en-us', 'de', 'ru-RU'];
$this->assertEquals('ru-ru', $request->getPreferredLanguage(['ru-ru']));
$request = new Request();
$request->acceptableLanguages = ['en-us', 'de'];
$this->assertEquals('ru-ru', $request->getPreferredLanguage(['ru-ru', 'pl']));
$this->assertEquals('ru-RU', $request->getPreferredLanguage(['ru-RU', 'pl']));
$request = new Request();
$request->acceptableLanguages = ['en-us', 'de'];
$this->assertEquals('pl', $request->getPreferredLanguage(['pl', 'ru-ru']));
}
public function testCsrfTokenValidation()
{
$this->mockWebApplication();
$request = new Request();
$request->enableCsrfCookie = false;
$token = $request->getCsrfToken();
// accept any value if CSRF validation is disabled
$request->enableCsrfValidation = false;
$this->assertTrue($request->validateCsrfToken($token));
$this->assertTrue($request->validateCsrfToken($token . 'a'));
$this->assertTrue($request->validateCsrfToken([]));
$this->assertTrue($request->validateCsrfToken([$token]));
$this->assertTrue($request->validateCsrfToken(0));
$this->assertTrue($request->validateCsrfToken(null));
// enable validation
$request->enableCsrfValidation = true;
// accept any value on GET request
foreach (['GET', 'HEAD', 'OPTIONS'] as $method) {
$_POST[$request->methodParam] = $method;
$this->assertTrue($request->validateCsrfToken($token));
$this->assertTrue($request->validateCsrfToken($token . 'a'));
$this->assertTrue($request->validateCsrfToken([]));
$this->assertTrue($request->validateCsrfToken([$token]));
$this->assertTrue($request->validateCsrfToken(0));
$this->assertTrue($request->validateCsrfToken(null));
}
// only accept valid token on POST
foreach (['POST', 'PUT', 'DELETE'] as $method) {
$_POST[$request->methodParam] = $method;
$this->assertTrue($request->validateCsrfToken($token));
$this->assertFalse($request->validateCsrfToken($token . 'a'));
$this->assertFalse($request->validateCsrfToken([]));
$this->assertFalse($request->validateCsrfToken([$token]));
$this->assertFalse($request->validateCsrfToken(0));
$this->assertFalse($request->validateCsrfToken(null));
}
}
/**
* test CSRF token validation by POST param
*/
public function testCsrfTokenPost()
{
$this->mockWebApplication();
$request = new Request();
$request->enableCsrfCookie = false;
$token = $request->getCsrfToken();
// accept no value on GET request
foreach (['GET', 'HEAD', 'OPTIONS'] as $method) {
$_POST[$request->methodParam] = $method;
$this->assertTrue($request->validateCsrfToken());
}
// only accept valid token on POST
foreach (['POST', 'PUT', 'DELETE'] as $method) {
$_POST[$request->methodParam] = $method;
$request->setBodyParams([]);
$this->assertFalse($request->validateCsrfToken());
$request->setBodyParams([$request->csrfParam => $token]);
$this->assertTrue($request->validateCsrfToken());
}
}
/**
* test CSRF token validation by POST param
*/
public function testCsrfTokenHeader()
{
$this->mockWebApplication();
$request = new Request();
$request->enableCsrfCookie = false;
$token = $request->getCsrfToken();
// accept no value on GET request
foreach (['GET', 'HEAD', 'OPTIONS'] as $method) {
$_POST[$request->methodParam] = $method;
$this->assertTrue($request->validateCsrfToken());
}
// only accept valid token on POST
foreach (['POST', 'PUT', 'DELETE'] as $method) {
$_POST[$request->methodParam] = $method;
$request->setBodyParams([]);
$request->headers->remove(Request::CSRF_HEADER);
$this->assertFalse($request->validateCsrfToken());
$request->headers->add(Request::CSRF_HEADER, $token);
$this->assertTrue($request->validateCsrfToken());
}
}
public function testResolve()
{
$this->mockWebApplication([
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'cache' => null,
'rules' => [
'posts' => 'post/list',
'post/<id>' => 'post/view',
],
],
],
]);
$request = new Request();
$request->pathInfo = 'posts';
$_GET['page'] = 1;
$result = $request->resolve();
$this->assertEquals(['post/list', ['page' => 1]], $result);
$this->assertEquals($_GET, ['page' => 1]);
$request->setQueryParams(['page' => 5]);
$result = $request->resolve();
$this->assertEquals(['post/list', ['page' => 5]], $result);
$this->assertEquals($_GET, ['page' => 1]);
$request->setQueryParams(['custom-page' => 5]);
$result = $request->resolve();
$this->assertEquals(['post/list', ['custom-page' => 5]], $result);
$this->assertEquals($_GET, ['page' => 1]);
unset($_GET['page']);
$request = new Request();
$request->pathInfo = 'post/21';
$this->assertEquals($_GET, []);
$result = $request->resolve();
$this->assertEquals(['post/view', ['id' => 21]], $result);
$this->assertEquals($_GET, ['id' => 21]);
$_GET['id'] = 42;
$result = $request->resolve();
$this->assertEquals(['post/view', ['id' => 21]], $result);
$this->assertEquals($_GET, ['id' => 21]);
$_GET['id'] = 63;
$request->setQueryParams(['token' => 'secret']);
$result = $request->resolve();
$this->assertEquals(['post/view', ['id' => 21, 'token' => 'secret']], $result);
$this->assertEquals($_GET, ['id' => 63]);
}
public function testGetHostInfo()
{
$request = new Request();
unset($_SERVER['SERVER_NAME'], $_SERVER['HTTP_HOST']);
$this->assertNull($request->getHostInfo());
$this->assertNull($request->getHostName());
$request->setHostInfo('http://servername.com:80');
$this->assertSame('http://servername.com:80', $request->getHostInfo());
$this->assertSame('servername.com', $request->getHostName());
}
/**
* @expectedException \yii\base\InvalidConfigException
*/
public function testGetScriptFileWithEmptyServer()
{
$request = new Request();
$_SERVER = [];
$request->getScriptFile();
}
/**
* @expectedException \yii\base\InvalidConfigException
*/
public function testGetScriptUrlWithEmptyServer()
{
$request = new Request();
$_SERVER = [];
$request->getScriptUrl();
}
public function testGetServerName()
{
$request = new Request();
$_SERVER['SERVER_NAME'] = 'servername';
$this->assertEquals('servername', $request->getServerName());
unset($_SERVER['SERVER_NAME']);
$this->assertEquals(null, $request->getServerName());
}
public function testGetServerPort()
{
$request = new Request();
$_SERVER['SERVER_PORT'] = 33;
$this->assertEquals(33, $request->getServerPort());
unset($_SERVER['SERVER_PORT']);
$this->assertEquals(null, $request->getServerPort());
}
public function testGetOrigin()
{
$_SERVER['HTTP_ORIGIN'] = 'https://www.w3.org';
$request = new Request();
$this->assertEquals('https://www.w3.org', $request->getOrigin());
unset($_SERVER['HTTP_ORIGIN']);
$request = new Request();
$this->assertEquals(null, $request->getOrigin());
}
}