Issue #1869548 by dawehner, jeqq, dmouse, slasher13, damiankloip, alexpott, nod_, AlxVallejo, chr.fritsch, yanniboi, effulgentsia, dixon_, -enzo-, Wim Leers, Crell, andypost, catch, Damien Tournoud, kim.pepper, linclark: Opt-in CORS support
parent
a1059ca508
commit
bc834169f0
|
@ -7,6 +7,49 @@
|
|||
"hash": "7d101b08e5ae002d827cd42ae9a4e344",
|
||||
"content-hash": "60f7057617c6d995bf9946d0b12f0b5d",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/asm89/stack-cors.git",
|
||||
"reference": "3ae8ef219bb4c9a6caf857421719aa07fa7776cc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/asm89/stack-cors/zipball/3ae8ef219bb4c9a6caf857421719aa07fa7776cc",
|
||||
"reference": "3ae8ef219bb4c9a6caf857421719aa07fa7776cc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"symfony/http-foundation": "~2.1|~3.0",
|
||||
"symfony/http-kernel": "~2.1|~3.0"
|
||||
},
|
||||
"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": "2016-08-01 12:05:04"
|
||||
},
|
||||
{
|
||||
"name": "composer/installers",
|
||||
"version": "v1.0.21",
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
"symfony/psr-http-message-bridge": "v0.2",
|
||||
"zendframework/zend-diactoros": "~1.1",
|
||||
"composer/semver": "~1.0",
|
||||
"paragonie/random_compat": "~1.0"
|
||||
"paragonie/random_compat": "~1.0",
|
||||
"asm89/stack-cors": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"behat/mink": "~1.7",
|
||||
|
|
|
@ -33,6 +33,14 @@ parameters:
|
|||
- sftp
|
||||
- webcal
|
||||
- rtsp
|
||||
cors.config:
|
||||
enabled: false
|
||||
allowedHeaders: []
|
||||
allowedMethods: []
|
||||
allowedOrigins: ['*']
|
||||
exposedHeaders: false
|
||||
maxAge: false
|
||||
supportsCredentials: false
|
||||
services:
|
||||
# Simple cache contexts, directly derived from the request context.
|
||||
cache_context.ip:
|
||||
|
@ -706,6 +714,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:
|
||||
|
|
|
@ -6,6 +6,7 @@ use Drupal\Core\Cache\Context\CacheContextsPass;
|
|||
use Drupal\Core\Cache\ListCacheBinsPass;
|
||||
use Drupal\Core\DependencyInjection\Compiler\AuthenticationProviderPass;
|
||||
use Drupal\Core\DependencyInjection\Compiler\BackendCompilerPass;
|
||||
use Drupal\Core\DependencyInjection\Compiler\CorsCompilerPass;
|
||||
use Drupal\Core\DependencyInjection\Compiler\GuzzleMiddlewarePass;
|
||||
use Drupal\Core\DependencyInjection\Compiler\ContextProvidersPass;
|
||||
use Drupal\Core\DependencyInjection\Compiler\ProxyServicesPass;
|
||||
|
@ -64,6 +65,8 @@ class CoreServiceProvider implements ServiceProviderInterface, ServiceModifierIn
|
|||
|
||||
$container->addCompilerPass(new BackendCompilerPass());
|
||||
|
||||
$container->addCompilerPass(new CorsCompilerPass());
|
||||
|
||||
$container->addCompilerPass(new StackedKernelPass());
|
||||
|
||||
$container->addCompilerPass(new StackedSessionHandlerPass());
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Provides a compiler pass which disables the CORS middleware in case disabled.
|
||||
*
|
||||
* @see core.services.yml
|
||||
*/
|
||||
class CorsCompilerPass implements CompilerPassInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container) {
|
||||
$enabled = FALSE;
|
||||
|
||||
if ($cors_config = $container->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');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\HttpKernel;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Tests CORS provided by Drupal.
|
||||
*
|
||||
* @see sites/default/default.services.yml
|
||||
* @see \Asm89\Stack\Cors
|
||||
* @see \Asm89\Stack\CorsService
|
||||
*
|
||||
* @group Http
|
||||
*/
|
||||
class CorsIntegrationTest extends KernelTestBase implements ServiceModifierInterface {
|
||||
|
||||
/**
|
||||
* The cors container configuration.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
protected $corsConfig = NULL;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'test_page_test'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('system', 'router');
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
}
|
||||
|
||||
public function testCrossSiteRequest() {
|
||||
|
||||
// Test default parameters.
|
||||
$cors_config = $this->container->getParameter('cors.config');
|
||||
$this->assertSame(FALSE, $cors_config['enabled']);
|
||||
$this->assertSame([], $cors_config['allowedHeaders']);
|
||||
$this->assertSame([], $cors_config['allowedMethods']);
|
||||
$this->assertSame(['*'], $cors_config['allowedOrigins']);
|
||||
|
||||
$this->assertSame(FALSE, $cors_config['exposedHeaders']);
|
||||
$this->assertSame(FALSE, $cors_config['maxAge']);
|
||||
$this->assertSame(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('/test-page');
|
||||
$request->headers->set('Origin', '');
|
||||
$cors_config['enabled'] = TRUE;
|
||||
$cors_config['allowedOrigins'] = ['http://example.com'];
|
||||
|
||||
$this->corsConfig = $cors_config;
|
||||
$this->container->get('kernel')->rebuildContainer();
|
||||
|
||||
/** @var \Symfony\Component\HttpFoundation\Response $response */
|
||||
$response = $this->container->get('http_kernel')->handle($request);
|
||||
$this->assertEquals(Response::HTTP_FORBIDDEN, $response->getStatusCode());
|
||||
$this->assertEquals('Not allowed.', $response->getContent());
|
||||
|
||||
// Specify a valid origin.
|
||||
$request->headers->set('Origin', 'http://example.com');
|
||||
$response = $this->container->get('http_kernel')->handle($request);
|
||||
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
if (isset($this->corsConfig)) {
|
||||
$container->setParameter('cors.config', $this->corsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -153,3 +153,22 @@ 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: ['*']
|
||||
# Sets the Access-Control-Expose-Headers header.
|
||||
exposedHeaders: false
|
||||
# Sets the Access-Control-Max-Age header.
|
||||
maxAge: false
|
||||
# Sets the Access-Control-Allow-Credentials header.
|
||||
supportsCredentials: false
|
||||
|
|
Loading…
Reference in New Issue