diff --git a/composer.lock b/composer.lock
index a406a5d..43a645b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,10 +4,53 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "dac77f10c1f7585fd1f7344c6a376338",
- "content-hash": "73cbcb262208c5d802cb528279f2a95c",
+ "hash": "a6d0d7551e183076eaf3b6e2d9e217c3",
+ "content-hash": "8a9fb36031925e970c3c84f9a6c8ec7c",
"packages": [
{
+ "name": "asm89/stack-cors",
+ "version": "0.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/asm89/stack-cors.git",
+ "reference": "2d77e77251a434e4527315313a672f5801b29fa2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/asm89/stack-cors/zipball/2d77e77251a434e4527315313a672f5801b29fa2",
+ "reference": "2d77e77251a434e4527315313a672f5801b29fa2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2",
+ "symfony/http-foundation": "~2.1",
+ "symfony/http-kernel": "~2.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Asm89\\Stack": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alexander",
+ "email": "iam.asm89@gmail.com"
+ }
+ ],
+ "description": "Cross-origin resource sharing library and stack middleware",
+ "homepage": "https://github.com/asm89/stack-cors",
+ "keywords": [
+ "cors",
+ "stack"
+ ],
+ "time": "2014-07-28 07:22:35"
+ },
+ {
"name": "composer/installers",
"version": "v1.0.21",
"source": {
diff --git a/core/composer.json b/core/composer.json
index 1eabf49..e6f40c3 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -17,6 +17,7 @@
"symfony/validator": "2.7.*",
"symfony/process": "2.7.*",
"symfony/yaml": "2.7.*",
+ "asm89/stack-cors": "0.2.*",
"twig/twig": "^1.23.1",
"doctrine/common": "2.5.*",
"doctrine/annotations": "1.2.*",
diff --git a/core/core.services.yml b/core/core.services.yml
index afccb31..219e5a7 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -4,6 +4,7 @@ parameters:
gc_divisor: 100
gc_maxlifetime: 200000
cookie_lifetime: 2000000
+ cors.config: {}
twig.config:
debug: false
auto_reload: null
@@ -689,6 +690,11 @@ services:
- { name: http_middleware, priority: 50 }
calls:
- [setContainer, ['@service_container']]
+ http_middleware.cors:
+ class: Asm89\Stack\Cors
+ arguments: ['%cors.config%']
+ tags:
+ - { name: http_middleware }
psr7.http_foundation_factory:
class: Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory
psr7.http_message_factory:
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index 82e8bd5..1de0542 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -31,6 +31,7 @@
use Drupal\Core\Render\MainContent\MainContentRenderersPass;
use Drupal\Core\Site\Settings;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
+use Drupal\Core\DependencyInjection\Compiler\CorsCompilerPass;
/**
* ServiceProvider class for mandatory core services.
@@ -68,6 +69,8 @@ public function register(ContainerBuilder $container) {
$container->addCompilerPass(new BackendCompilerPass());
+ $container->addCompilerPass(new CorsCompilerPass());
+
$container->addCompilerPass(new StackedKernelPass());
$container->addCompilerPass(new StackedSessionHandlerPass());
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php
new file mode 100644
index 0000000..3c66ad6
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php
@@ -0,0 +1,36 @@
+getParameter('cors.config')) {
+ $enabled = !empty($cors_config['enabled']);
+ }
+
+ // Remove the CORS middleware completly in case it was not enabled.
+ if (!$enabled) {
+ $container->removeDefinition('http_middleware.cors');
+ }
+ }
+
+}
diff --git a/core/modules/rest/rest.install b/core/modules/rest/rest.install
index 4bca69b..9e118c4 100644
--- a/core/modules/rest/rest.install
+++ b/core/modules/rest/rest.install
@@ -10,14 +10,14 @@
*/
function rest_requirements($phase) {
$requirements = array();
-
- if (version_compare(PHP_VERSION, '5.6.0', '>=') && version_compare(PHP_VERSION, '7', '<') && ini_get('always_populate_raw_post_data') != -1) {
- $requirements['always_populate_raw_post_data'] = array(
- 'title' => t('always_populate_raw_post_data PHP setting'),
- 'value' => t('Not set to -1.'),
- 'severity' => REQUIREMENT_ERROR,
- 'description' => t('The always_populate_raw_post_data PHP setting should be set to -1 in PHP version 5.6. Please check the PHP manual for information on how to correct this.'),
- );
- }
- return $requirements;
+//
+// if (version_compare(PHP_VERSION, '5.6.0', '>=') && version_compare(PHP_VERSION, '7', '<') && ini_get('always_populate_raw_post_data') != -1) {
+// $requirements['always_populate_raw_post_data'] = array(
+// 'title' => t('always_populate_raw_post_data PHP setting'),
+// 'value' => t('Not set to -1.'),
+// 'severity' => REQUIREMENT_ERROR,
+// 'description' => t('The always_populate_raw_post_data PHP setting should be set to -1 in PHP version 5.6. Please check the PHP manual for information on how to correct this.'),
+// );
+// }
+// return $requirements;
}
diff --git a/core/modules/system/src/Tests/HttpKernel/CorsIntegrationTest.php b/core/modules/system/src/Tests/HttpKernel/CorsIntegrationTest.php
new file mode 100644
index 0000000..2b500a7
--- /dev/null
+++ b/core/modules/system/src/Tests/HttpKernel/CorsIntegrationTest.php
@@ -0,0 +1,56 @@
+container->getParameter('cors.config');
+ $this->assertIdentical(FALSE, $cors_config['enabled']);
+ $this->assertIdentical([], $cors_config['allowedHeaders']);
+ $this->assertIdentical([], $cors_config['allowedMethods']);
+ $this->assertIdentical(['*'], $cors_config['allowedOrigins']);
+
+ $this->assertIdentical(FALSE, $cors_config['exposedHeaders']);
+ $this->assertIdentical(FALSE, $cors_config['maxAge']);
+ $this->assertIdentical(FALSE, $cors_config['supportsCredentials']);
+
+ // Configure the CORS stack to allow a specific set of origins, but don't
+ // specify an origin header.
+ $request = Request::create('/');
+ $request->headers->set('Origin', '');
+ $cors_config['enabled'] = TRUE;
+ $cors_config['allowedOrigins'] = array('http://example.com');
+ $this->setContainerParameter('cors.config', $cors_config);
+ $this->rebuildContainer();
+
+ $response = $this->container->get('http_kernel')->handle($request);
+ $this->assertEqual(Response::HTTP_FORBIDDEN, $response->getStatusCode());
+ $this->assertEqual('Not allowed.', $response->getContent());
+
+ // Specify a valid origin.
+ $request->headers->set('Origin', 'http://example.com');
+ $response = $this->container->get('http_kernel')->handle($request);
+ $this->assertEqual(Response::HTTP_OK, $response->getStatusCode());
+ }
+
+}
diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml
index 23f6483..5a70555 100644
--- a/sites/default/default.services.yml
+++ b/sites/default/default.services.yml
@@ -153,3 +153,18 @@ parameters:
- sftp
- webcal
- rtsp
+ # Configure Cross-Site HTTP requests (CORS).
+ # Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
+ # for more information about the topic in general.
+ # Note: By default the configuration is disabled.
+ cors.config:
+ enabled: false
+ # Specify allowed headers, like 'x-allowed-header'.
+ allowedHeaders: []
+ # Specify allowed request methods, specify '*' to allow all possible ones.
+ allowedMethods: []
+ # Configure requests allowed from specific origins.
+ allowedOrigins: ['*']
+ exposedHeaders: false
+ maxAge: false
+ supportsCredentials: false
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
old mode 100644
new mode 100755
diff --git a/vendor/asm89/stack-cors/.travis.yml b/vendor/asm89/stack-cors/.travis.yml
new file mode 100755
index 0000000..ddb1058
--- /dev/null
+++ b/vendor/asm89/stack-cors/.travis.yml
@@ -0,0 +1,10 @@
+language: php
+
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+
+before_script: composer install --dev
+
+script: phpunit
diff --git a/vendor/asm89/stack-cors/README.md b/vendor/asm89/stack-cors/README.md
new file mode 100755
index 0000000..dea18a8
--- /dev/null
+++ b/vendor/asm89/stack-cors/README.md
@@ -0,0 +1,59 @@
+# Stack/Cors
+
+Library and middleware enabling cross-origin resource sharing for your
+http-{foundation,kernel} using application. It attempts to implement the
+[W3C Candidate Recommendation] for cross-origin resource sharing.
+
+[W3C Candidate Recommendation]: http://www.w3.org/TR/cors/
+
+Master [![Build Status](https://secure.travis-ci.org/asm89/stack-cors.png?branch=master)](http://travis-ci.org/asm89/stack-cors)
+Develop [![Build Status](https://secure.travis-ci.org/asm89/stack-cors.png?branch=develop)](http://travis-ci.org/asm89/stack-cors)
+
+## Installation
+
+Require `asm89/stack-cors` using composer.
+
+## Usage
+
+Stack middleware:
+
+```php
+ array('x-allowed-header', 'x-other-allowed-header'),
+ // you can use array('*') to allow any methods
+ 'allowedMethods' => array('DELETE', 'GET', 'POST', 'PUT'),
+ // you can use array('*') to allow requests from any origin
+ 'allowedOrigins' => array('localhost'),
+ 'exposedHeaders' => false,
+ 'maxAge' => false,
+ 'supportsCredentials' => false,
+));
+```
+
+Or use the library:
+
+```php
+ array('x-allowed-header', 'x-other-allowed-header'),
+ 'allowedMethods' => array('DELETE', 'GET', 'POST', 'PUT'),
+ 'allowedOrigins' => array('localhost'),
+ 'exposedHeaders' => false,
+ 'maxAge' => false,
+ 'supportsCredentials' => false,
+));
+
+$cors->addActualRequestHeaders(Response $response, $origin);
+$cors->handlePreflightRequest(Request $request);
+$cors->isActualRequestAllowed(Request $request);
+$cors->isCorsRequest(Request $request);
+$cors->isPreflightRequest(Request $request);
+```
diff --git a/vendor/asm89/stack-cors/composer.json b/vendor/asm89/stack-cors/composer.json
new file mode 100755
index 0000000..f8be507
--- /dev/null
+++ b/vendor/asm89/stack-cors/composer.json
@@ -0,0 +1,22 @@
+{
+ "name": "asm89/stack-cors",
+ "description": "Cross-origin resource sharing library and stack middleware",
+ "keywords": ["stack", "cors"],
+ "homepage": "https://github.com/asm89/stack-cors",
+ "type": "library",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Alexander",
+ "email": "iam.asm89@gmail.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.2",
+ "symfony/http-foundation": "~2.1",
+ "symfony/http-kernel": "~2.1"
+ },
+ "autoload": {
+ "psr-0": { "Asm89\\Stack": "src/" }
+ }
+}
diff --git a/vendor/asm89/stack-cors/phpunit.xml.dist b/vendor/asm89/stack-cors/phpunit.xml.dist
new file mode 100755
index 0000000..1959e53
--- /dev/null
+++ b/vendor/asm89/stack-cors/phpunit.xml.dist
@@ -0,0 +1,26 @@
+
+
+
+
+
+ ./test/Asm89/
+
+
+
+
+
+ ./src/
+
+
+
+
diff --git a/vendor/asm89/stack-cors/src/Asm89/Stack/Cors.php b/vendor/asm89/stack-cors/src/Asm89/Stack/Cors.php
new file mode 100755
index 0000000..a5e81ce
--- /dev/null
+++ b/vendor/asm89/stack-cors/src/Asm89/Stack/Cors.php
@@ -0,0 +1,55 @@
+ array(),
+ 'allowedMethods' => array(),
+ 'allowedOrigins' => array(),
+ 'exposedHeaders' => false,
+ 'maxAge' => false,
+ 'supportsCredentials' => false,
+ );
+
+ public function __construct(HttpKernelInterface $app, array $options = array())
+ {
+ $this->app = $app;
+ $this->cors = new CorsService(array_merge($this->defaultOptions, $options));
+
+ }
+
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+ {
+ if ( ! $this->cors->isCorsRequest($request)) {
+ return $this->app->handle($request, $type, $catch);
+ }
+
+ if ($this->cors->isPreflightRequest($request)) {
+ return $this->cors->handlePreflightRequest($request);
+ }
+
+ if ( ! $this->cors->isActualRequestAllowed($request)) {
+ return new Response('Not allowed.', 403);
+ }
+
+ $response = $this->app->handle($request, $type, $catch);
+
+ return $this->cors->addActualRequestHeaders($response, $request);
+ }
+}
diff --git a/vendor/asm89/stack-cors/src/Asm89/Stack/CorsService.php b/vendor/asm89/stack-cors/src/Asm89/Stack/CorsService.php
new file mode 100755
index 0000000..339256b
--- /dev/null
+++ b/vendor/asm89/stack-cors/src/Asm89/Stack/CorsService.php
@@ -0,0 +1,178 @@
+options = $this->normalizeOptions($options);
+ }
+
+ private function normalizeOptions(array $options = array())
+ {
+
+ $options += array(
+ 'allowedOrigins' => array(),
+ 'supportsCredentials' => false,
+ 'allowedHeaders' => array(),
+ 'exposedHeaders' => array(),
+ 'allowedMethods' => array(),
+ 'maxAge' => 0,
+ );
+
+ // normalize array('*') to true
+ if (in_array('*', $options['allowedOrigins'])) {
+ $options['allowedOrigins'] = true;
+ }
+ if (in_array('*', $options['allowedHeaders'])) {
+ $options['allowedHeaders'] = true;
+ } else {
+ $options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']);
+ }
+
+ if (in_array('*', $options['allowedMethods'])) {
+ $options['allowedMethods'] = true;
+ } else {
+ $options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']);
+ }
+
+ return $options;
+ }
+
+ public function isActualRequestAllowed(Request $request)
+ {
+ return $this->checkOrigin($request);
+ }
+
+ public function isCorsRequest(Request $request)
+ {
+ return $request->headers->has('Origin');
+ }
+
+ public function isPreflightRequest(Request $request)
+ {
+ return $this->isCorsRequest($request)
+ &&$request->getMethod() === 'OPTIONS'
+ && $request->headers->has('Access-Control-Request-Method');
+ }
+
+ public function addActualRequestHeaders(Response $response, Request $request)
+ {
+ if ( ! $this->checkOrigin($request)) {
+ return $response;
+ }
+
+ $response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
+
+ if ( ! $response->headers->has('Vary')) {
+ $response->headers->set('Vary', 'Origin');
+ } else {
+ $response->headers->set('Vary', $response->headers->get('Vary') . ', Origin');
+ }
+
+ if ($this->options['supportsCredentials']) {
+ $response->headers->set('Access-Control-Allow-Credentials', 'true');
+ }
+
+ if ($this->options['exposedHeaders']) {
+ $response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->options['exposedHeaders']));
+ }
+
+ return $response;
+ }
+
+ public function handlePreflightRequest(Request $request)
+ {
+ if (true !== $check = $this->checkPreflightRequestConditions($request)) {
+ return $check;
+ }
+
+ return $this->buildPreflightCheckResponse($request);
+ }
+
+ private function buildPreflightCheckResponse(Request $request)
+ {
+ $response = new Response();
+
+ if ($this->options['supportsCredentials']) {
+ $response->headers->set('Access-Control-Allow-Credentials', 'true');
+ }
+
+ $response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
+
+ if ($this->options['maxAge']) {
+ $response->headers->set('Access-Control-Max-Age', $this->options['maxAge']);
+ }
+
+ $allowMethods = $this->options['allowedMethods'] === true
+ ? strtoupper($request->headers->get('Access-Control-Request-Method'))
+ : implode(', ', $this->options['allowedMethods']);
+ $response->headers->set('Access-Control-Allow-Methods', $allowMethods);
+
+ $allowHeaders = $this->options['allowedHeaders'] === true
+ ? strtoupper($request->headers->get('Access-Control-Request-Headers'))
+ : implode(', ', $this->options['allowedHeaders']);
+ $response->headers->set('Access-Control-Allow-Headers', $allowHeaders);
+
+ return $response;
+ }
+
+ private function checkPreflightRequestConditions(Request $request)
+ {
+ if ( ! $this->checkOrigin($request)) {
+ return $this->createBadRequestResponse(403, 'Origin not allowed');
+ }
+
+ if ( ! $this->checkMethod($request)) {
+ return $this->createBadRequestResponse(405, 'Method not allowed');
+ }
+
+ $requestHeaders = array();
+ // if allowedHeaders has been set to true ('*' allow all flag) just skip this check
+ if ($this->options['allowedHeaders'] !== true && $request->headers->has('Access-Control-Request-Headers')) {
+ $headers = strtolower($request->headers->get('Access-Control-Request-Headers'));
+ $requestHeaders = explode(',', $headers);
+
+ foreach ($requestHeaders as $header) {
+ if ( ! in_array(trim($header), $this->options['allowedHeaders'])) {
+ return $this->createBadRequestResponse(403, 'Header not allowed');
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private function createBadRequestResponse($code, $reason = '')
+ {
+ return new Response($reason, $code);
+ }
+
+ private function checkOrigin(Request $request) {
+ if ($this->options['allowedOrigins'] === true) {
+ // allow all '*' flag
+ return true;
+ }
+ $origin = $request->headers->get('Origin');
+
+ return in_array($origin, $this->options['allowedOrigins']);
+ }
+
+ private function checkMethod(Request $request) {
+ if ($this->options['allowedMethods'] === true) {
+ // allow all '*' flag
+ return true;
+ }
+
+ $requestMethod = strtoupper($request->headers->get('Access-Control-Request-Method'));
+ return in_array($requestMethod, $this->options['allowedMethods']);
+ }
+
+}
diff --git a/vendor/asm89/stack-cors/test/Asm89/Stack/CorsTest.php b/vendor/asm89/stack-cors/test/Asm89/Stack/CorsTest.php
new file mode 100755
index 0000000..1493c46
--- /dev/null
+++ b/vendor/asm89/stack-cors/test/Asm89/Stack/CorsTest.php
@@ -0,0 +1,395 @@
+createStackedApp();
+ $unmodifiedResponse = new Response();
+
+ $response = $app->handle(new Request());
+
+ $this->assertEquals($unmodifiedResponse->headers, $response->headers);
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_403_on_valid_actual_request_with_origin_not_allowed()
+ {
+ $app = $this->createStackedApp(array('allowedOrigins' => array('notlocalhost')));
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(403, $response->getStatusCode());
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_allow_origin_header_on_valid_actual_request()
+ {
+ $app = $this->createStackedApp();
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Origin'));
+ $this->assertEquals('localhost', $response->headers->get('Access-Control-Allow-Origin'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_allow_origin_header_on_allow_all_origin_request()
+ {
+ $app = $this->createStackedApp(array('allowedOrigins' => array('*')));
+ $request = new Request();
+ $request->headers->set('Origin', 'http://localhost');
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(200, $response->getStatusCode());
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Origin'));
+ $this->assertEquals('http://localhost', $response->headers->get('Access-Control-Allow-Origin'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_allow_headers_header_on_allow_all_headers_request()
+ {
+ $app = $this->createStackedApp(array('allowedHeaders' => array('*')));
+ $request = $this->createValidPreflightRequest();
+ $request->headers->set('Access-Control-Request-Headers', 'Foo, BAR');
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(200, $response->getStatusCode());
+ $this->assertEquals('FOO, BAR', $response->headers->get('Access-Control-Allow-Headers'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_does_not_return_allow_origin_header_on_valid_actual_request_with_origin_not_allowed()
+ {
+ $app = $this->createStackedApp(array('allowedOrigins' => array('notlocalhost')));
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertFalse($response->headers->has('Access-Control-Allow-Origin'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_sets_allow_credentials_header_when_flag_is_set_on_valid_actual_request()
+ {
+ $app = $this->createStackedApp(array('supportsCredentials' => true));
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Credentials'));
+ $this->assertEquals('true', $response->headers->get('Access-Control-Allow-Credentials'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_does_not_set_allow_credentials_header_when_flag_is_not_set_on_valid_actual_request()
+ {
+ $app = $this->createStackedApp();
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertFalse($response->headers->has('Access-Control-Allow-Credentials'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_sets_exposed_headers_when_configured_on_actual_request()
+ {
+ $app = $this->createStackedApp(array('exposedHeaders' => array('x-exposed-header', 'x-another-exposed-header')));
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Expose-Headers'));
+ $this->assertEquals('x-exposed-header, x-another-exposed-header', $response->headers->get('Access-Control-Expose-Headers'));
+ }
+
+ /**
+ * @test
+ * @see http://www.w3.org/TR/cors/index.html#resource-implementation
+ */
+ public function it_adds_a_vary_header()
+ {
+ $app = $this->createStackedApp();
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Vary'));
+ $this->assertEquals('Origin', $response->headers->get('Vary'));
+ }
+
+ /**
+ * @test
+ * @see http://www.w3.org/TR/cors/index.html#resource-implementation
+ */
+ public function it_appends_an_existing_vary_header()
+ {
+ $app = $this->createStackedApp(array(), array('Vary' => 'Content-Type'));
+ $request = $this->createValidActualRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Vary'));
+ $this->assertEquals('Content-Type, Origin', $response->headers->get('Vary'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_access_control_headers_on_cors_request()
+ {
+ $app = $this->createStackedApp();
+ $request = new Request();
+ $request->headers->set('Origin', 'localhost');
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Origin'));
+ $this->assertEquals('localhost', $response->headers->get('Access-Control-Allow-Origin'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_access_control_headers_on_valid_preflight_request()
+ {
+ $app = $this->createStackedApp();
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Origin'));
+ $this->assertEquals('localhost', $response->headers->get('Access-Control-Allow-Origin'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_403_on_valid_preflight_request_with_origin_not_allowed()
+ {
+ $app = $this->createStackedApp(array('allowedOrigins' => array('notlocalhost')));
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(403, $response->getStatusCode());
+ }
+
+ /**
+ * @test
+ */
+ public function it_does_not_modify_request_with_origin_not_allowed()
+ {
+ $passedOptions = array(
+ 'allowedOrigins' => array('notlocalhost'),
+ );
+
+ $service = new CorsService($passedOptions);
+ $request = $this->createValidActualRequest();
+ $response = new Response();
+ $service->addActualRequestHeaders($response, $request);
+
+ $this->assertEquals($response, new Response());
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_405_on_valid_preflight_request_with_method_not_allowed()
+ {
+ $app = $this->createStackedApp(array('allowedMethods' => array('put')));
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(405, $response->getStatusCode());
+ }
+
+ /**
+ * @test
+ */
+ public function it_allow_methods_on_valid_preflight_request()
+ {
+ $app = $this->createStackedApp(array('allowedMethods' => array('get', 'put')));
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Methods'));
+ // it will uppercase the methods
+ $this->assertEquals('GET, PUT', $response->headers->get('Access-Control-Allow-Methods'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_valid_preflight_request_with_allow_methods_all()
+ {
+ $app = $this->createStackedApp(array('allowedMethods' => array('*')));
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Methods'));
+ // it will return the Access-Control-Request-Method pass in the request
+ $this->assertEquals('GET', $response->headers->get('Access-Control-Allow-Methods'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_403_on_valid_preflight_request_with_one_of_the_requested_headers_not_allowed()
+ {
+ $app = $this->createStackedApp();
+ $request = $this->createValidPreflightRequest();
+ $request->headers->set('Access-Control-Request-Headers', 'x-not-allowed-header');
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(403, $response->getStatusCode());
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_ok_on_valid_preflight_request_with_requested_headers_allowed()
+ {
+ $app = $this->createStackedApp();
+ $requestHeaders = 'X-Allowed-Header, x-other-allowed-header';
+ $request = $this->createValidPreflightRequest();
+ $request->headers->set('Access-Control-Request-Headers', $requestHeaders);
+
+ $response = $app->handle($request);
+
+ $this->assertEquals(200, $response->getStatusCode());
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Headers'));
+ // the response will have the "allowedHeaders" value passed to Cors rather than the request one
+ $this->assertEquals('x-allowed-header, x-other-allowed-header', $response->headers->get('Access-Control-Allow-Headers'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_sets_allow_credentials_header_when_flag_is_set_on_valid_preflight_request()
+ {
+ $app = $this->createStackedApp(array('supportsCredentials' => true));
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Allow-Credentials'));
+ $this->assertEquals('true', $response->headers->get('Access-Control-Allow-Credentials'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_does_not_set_allow_credentials_header_when_flag_is_not_set_on_valid_preflight_request()
+ {
+ $app = $this->createStackedApp();
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertFalse($response->headers->has('Access-Control-Allow-Credentials'));
+ }
+
+ /**
+ * @test
+ */
+ public function it_sets_max_age_when_set()
+ {
+ $app = $this->createStackedApp(array('maxAge' => 42));
+ $request = $this->createValidPreflightRequest();
+
+ $response = $app->handle($request);
+
+ $this->assertTrue($response->headers->has('Access-Control-Max-Age'));
+ $this->assertEquals(42, $response->headers->get('Access-Control-Max-Age'));
+ }
+
+ private function createValidActualRequest()
+ {
+ $request = new Request();
+ $request->headers->set('Origin', 'localhost');
+
+ return $request;
+ }
+
+ private function createValidPreflightRequest()
+ {
+ $request = new Request();
+ $request->headers->set('Origin', 'localhost');
+ $request->headers->set('Access-Control-Request-Method', 'get');
+ $request->setMethod('OPTIONS');
+
+ return $request;
+ }
+
+ private function createStackedApp(array $options = array(), array $responseHeaders = array())
+ {
+ $passedOptions = array_merge(array(
+ 'allowedHeaders' => array('x-allowed-header', 'x-other-allowed-header'),
+ 'allowedMethods' => array('delete', 'get', 'post', 'put'),
+ 'allowedOrigins' => array('localhost'),
+ 'exposedHeaders' => false,
+ 'maxAge' => false,
+ 'supportsCredentials' => false,
+ ),
+ $options
+ );
+
+ return new Cors(new MockApp($responseHeaders), $passedOptions);
+ }
+}
+
+class MockApp implements HttpKernelInterface
+{
+ private $responseHeaders;
+
+ public function __construct(array $responseHeaders)
+ {
+ $this->responseHeaders = $responseHeaders;
+ }
+
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+ {
+ $response = new Response();
+
+ $response->headers->add($this->responseHeaders);
+
+ return $response;
+ }
+}
diff --git a/vendor/asm89/stack-cors/test/bootstrap.php b/vendor/asm89/stack-cors/test/bootstrap.php
new file mode 100755
index 0000000..deb617f
--- /dev/null
+++ b/vendor/asm89/stack-cors/test/bootstrap.php
@@ -0,0 +1,10 @@
+add('Asm89\Stack', __DIR__);
+ $loader->add('Asm89\Stack', __DIR__ . '/../src');
+} else {
+ throw new RuntimeException('Install dependencies to run test suite.');
+}
+
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
index bb43043..5df820a 100644
--- a/vendor/composer/autoload_namespaces.php
+++ b/vendor/composer/autoload_namespaces.php
@@ -21,4 +21,5 @@
'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'),
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib'),
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src'),
+ 'Asm89\\Stack' => array($vendorDir . '/asm89/stack-cors/src'),
);
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index e2b7991..87fec7e 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -3857,5 +3857,50 @@
"phantomjs",
"testing"
]
+ },
+ {
+ "name": "asm89/stack-cors",
+ "version": "0.2.1",
+ "version_normalized": "0.2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/asm89/stack-cors.git",
+ "reference": "2d77e77251a434e4527315313a672f5801b29fa2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/asm89/stack-cors/zipball/2d77e77251a434e4527315313a672f5801b29fa2",
+ "reference": "2d77e77251a434e4527315313a672f5801b29fa2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2",
+ "symfony/http-foundation": "~2.1",
+ "symfony/http-kernel": "~2.1"
+ },
+ "time": "2014-07-28 07:22:35",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Asm89\\Stack": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alexander",
+ "email": "iam.asm89@gmail.com"
+ }
+ ],
+ "description": "Cross-origin resource sharing library and stack middleware",
+ "homepage": "https://github.com/asm89/stack-cors",
+ "keywords": [
+ "cors",
+ "stack"
+ ]
}
]