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()); } }