CorsIntegrationTest.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. namespace Drupal\FunctionalTests\HttpKernel;
  3. use Drupal\Core\Url;
  4. use Drupal\Tests\BrowserTestBase;
  5. /**
  6. * Tests CORS provided by Drupal.
  7. *
  8. * @see sites/default/default.services.yml
  9. * @see \Asm89\Stack\Cors
  10. * @see \Asm89\Stack\CorsService
  11. *
  12. * @group Http
  13. */
  14. class CorsIntegrationTest extends BrowserTestBase {
  15. /**
  16. * {@inheritdoc}
  17. */
  18. public static $modules = ['system', 'test_page_test', 'page_cache'];
  19. /**
  20. * {@inheritdoc}
  21. */
  22. protected $defaultTheme = 'stark';
  23. public function testCrossSiteRequest() {
  24. // Test default parameters.
  25. $cors_config = $this->container->getParameter('cors.config');
  26. $this->assertSame(FALSE, $cors_config['enabled']);
  27. $this->assertSame([], $cors_config['allowedHeaders']);
  28. $this->assertSame([], $cors_config['allowedMethods']);
  29. $this->assertSame(['*'], $cors_config['allowedOrigins']);
  30. $this->assertSame(FALSE, $cors_config['exposedHeaders']);
  31. $this->assertSame(FALSE, $cors_config['maxAge']);
  32. $this->assertSame(FALSE, $cors_config['supportsCredentials']);
  33. // Enable CORS with the default options.
  34. $cors_config['enabled'] = TRUE;
  35. $this->setContainerParameter('cors.config', $cors_config);
  36. $this->rebuildContainer();
  37. // Fire off a request.
  38. $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
  39. $this->assertSession()->statusCodeEquals(200);
  40. $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'MISS');
  41. $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
  42. // Fire the same exact request. This time it should be cached.
  43. $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
  44. $this->assertSession()->statusCodeEquals(200);
  45. $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'HIT');
  46. $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
  47. // Fire a request for a different origin. Verify the CORS header.
  48. $this->drupalGet('/test-page', [], ['Origin' => 'http://example.org']);
  49. $this->assertSession()->statusCodeEquals(200);
  50. $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'HIT');
  51. $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.org');
  52. // Configure the CORS stack to allow a specific set of origins.
  53. $cors_config['allowedOrigins'] = ['http://example.com'];
  54. $this->setContainerParameter('cors.config', $cors_config);
  55. $this->rebuildContainer();
  56. // Fire a request from an origin that isn't allowed.
  57. /** @var \Symfony\Component\HttpFoundation\Response $response */
  58. $this->drupalGet('/test-page', [], ['Origin' => 'http://non-valid.com']);
  59. $this->assertSession()->statusCodeEquals(403);
  60. $this->assertSession()->pageTextContains('Not allowed.');
  61. // Specify a valid origin.
  62. $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
  63. $this->assertSession()->statusCodeEquals(200);
  64. $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
  65. // Verify POST still functions with 'Origin' header set to site's domain.
  66. $origin = \Drupal::request()->getSchemeAndHttpHost();
  67. /** @var \GuzzleHttp\ClientInterface $httpClient */
  68. $httpClient = $this->getSession()->getDriver()->getClient()->getClient();
  69. $url = Url::fromUri('base:/test-page');
  70. $response = $httpClient->request('POST', $url->setAbsolute()->toString(), [
  71. 'headers' => [
  72. 'Origin' => $origin,
  73. ],
  74. ]);
  75. $this->assertEquals(200, $response->getStatusCode());
  76. }
  77. }