function CorsIntegrationTest::testCrossSiteRequest

Same name in other branches
  1. 9 core/tests/Drupal/FunctionalTests/HttpKernel/CorsIntegrationTest.php \Drupal\FunctionalTests\HttpKernel\CorsIntegrationTest::testCrossSiteRequest()
  2. 8.9.x core/tests/Drupal/FunctionalTests/HttpKernel/CorsIntegrationTest.php \Drupal\FunctionalTests\HttpKernel\CorsIntegrationTest::testCrossSiteRequest()
  3. 10 core/tests/Drupal/FunctionalTests/HttpKernel/CorsIntegrationTest.php \Drupal\FunctionalTests\HttpKernel\CorsIntegrationTest::testCrossSiteRequest()

File

core/tests/Drupal/FunctionalTests/HttpKernel/CorsIntegrationTest.php, line 31

Class

CorsIntegrationTest
Tests CORS provided by Drupal.

Namespace

Drupal\FunctionalTests\HttpKernel

Code

public function testCrossSiteRequest() : void {
    // Test default parameters.
    $cors_config = $this->container
        ->getParameter('cors.config');
    $this->assertFalse($cors_config['enabled']);
    $this->assertSame([], $cors_config['allowedHeaders']);
    $this->assertSame([], $cors_config['allowedMethods']);
    $this->assertSame([
        '*',
    ], $cors_config['allowedOrigins']);
    $this->assertFalse($cors_config['exposedHeaders']);
    $this->assertFalse($cors_config['maxAge']);
    $this->assertFalse($cors_config['supportsCredentials']);
    // Enable CORS with the default options.
    $cors_config['enabled'] = TRUE;
    $this->setContainerParameter('cors.config', $cors_config);
    $this->rebuildContainer();
    // Fire off a request.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://example.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('X-Drupal-Cache', 'MISS');
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', '*');
    $this->assertSession()
        ->responseHeaderNotContains('Vary', 'Origin');
    // Fire the same exact request. This time it should be cached.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://example.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('X-Drupal-Cache', 'HIT');
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', '*');
    $this->assertSession()
        ->responseHeaderNotContains('Vary', 'Origin');
    // Fire a request for a different origin. Verify the CORS header.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://example.org',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('X-Drupal-Cache', 'HIT');
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', '*');
    $this->assertSession()
        ->responseHeaderNotContains('Vary', 'Origin');
    // Configure the CORS stack to match allowed origins using regex patterns.
    $cors_config['allowedOrigins'] = [];
    $cors_config['allowedOriginsPatterns'] = [
        '#^http://[a-z-]*\\.valid.com$#',
    ];
    $this->setContainerParameter('cors.config', $cors_config);
    $this->rebuildContainer();
    // Fire a request from an origin that isn't allowed.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://non-valid.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderDoesNotExist('Access-Control-Allow-Origin');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Specify a valid origin.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://sub-domain.valid.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'http://sub-domain.valid.com');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Test combining allowedOrigins and allowedOriginsPatterns.
    $cors_config['allowedOrigins'] = [
        'http://domainA.com',
    ];
    $cors_config['allowedOriginsPatterns'] = [
        '#^http://domain[B-Z-]*\\.com$#',
    ];
    $this->setContainerParameter('cors.config', $cors_config);
    $this->rebuildContainer();
    // Specify an origin that does not match allowedOrigins nor
    // allowedOriginsPattern.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://non-valid.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderDoesNotExist('Access-Control-Allow-Origin');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Specify a valid origin that matches allowedOrigins.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://domainA.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'http://domainA.com');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Specify a valid origin that matches allowedOriginsPatterns.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://domainX.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'http://domainX.com');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Configure the CORS stack to allow a specific origin.
    $cors_config['allowedOrigins'] = [
        'http://example.com',
    ];
    $cors_config['allowedOriginsPatterns'] = [];
    $this->setContainerParameter('cors.config', $cors_config);
    $this->rebuildContainer();
    // Fire a request from an origin that isn't allowed.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://non-valid.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
    $this->assertSession()
        ->responseHeaderNotContains('Vary', 'Origin');
    // Specify a valid origin.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://example.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
    $this->assertSession()
        ->responseHeaderNotContains('Vary', 'Origin');
    // Configure the CORS stack to allow a specific set of origins.
    $cors_config['allowedOrigins'] = [
        'http://example.com',
        'https://drupal.org',
    ];
    $this->setContainerParameter('cors.config', $cors_config);
    $this->rebuildContainer();
    // Fire a request from an origin that isn't allowed.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://non-valid.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', NULL);
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Specify a valid origin.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'http://example.com',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Specify a valid origin.
    $this->drupalGet('/test-page', [], [
        'Origin' => 'https://drupal.org',
    ]);
    $this->assertSession()
        ->statusCodeEquals(200);
    $this->assertSession()
        ->responseHeaderEquals('Access-Control-Allow-Origin', 'https://drupal.org');
    $this->assertSession()
        ->responseHeaderContains('Vary', 'Origin');
    // Verify POST still functions with 'Origin' header set to site's domain.
    $origin = \Drupal::request()->getSchemeAndHttpHost();
    
    /** @var \GuzzleHttp\ClientInterface $httpClient */
    $httpClient = $this->getSession()
        ->getDriver()
        ->getClient()
        ->getClient();
    $url = Url::fromUri('base:/test-page');
    
    /** @var \Symfony\Component\HttpFoundation\Response $response */
    $response = $httpClient->request('POST', $url->setAbsolute()
        ->toString(), [
        'headers' => [
            'Origin' => $origin,
        ],
    ]);
    $this->assertEquals(200, $response->getStatusCode());
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.