CorsBuilderTest.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. declare(strict_types=1);
  3. namespace Cake\Test\TestCase\Http;
  4. use Cake\Http\CorsBuilder;
  5. use Cake\Http\Response;
  6. use Cake\TestSuite\TestCase;
  7. class CorsBuilderTest extends TestCase
  8. {
  9. /**
  10. * test allowOrigin() setting allow-origin
  11. */
  12. public function testAllowOriginNoOrigin(): void
  13. {
  14. $response = new Response();
  15. $builder = new CorsBuilder($response, '');
  16. $this->assertSame($builder, $builder->allowOrigin(['*.example.com', '*.foo.com']));
  17. $this->assertNoHeader($builder->build(), 'Access-Control-Origin');
  18. }
  19. /**
  20. * test allowOrigin() setting allow-origin
  21. */
  22. public function testAllowOrigin(): void
  23. {
  24. $response = new Response();
  25. $builder = new CorsBuilder($response, 'http://www.example.com');
  26. $this->assertSame($builder, $builder->allowOrigin('*'));
  27. $this->assertHeader('*', $builder->build(), 'Access-Control-Allow-Origin');
  28. $response = new Response();
  29. $builder = new CorsBuilder($response, 'http://www.example.com');
  30. $this->assertSame($builder, $builder->allowOrigin(['*.example.com', '*.foo.com']));
  31. $builder->build();
  32. $this->assertHeader('http://www.example.com', $builder->build(), 'Access-Control-Allow-Origin');
  33. $response = new Response();
  34. $builder = new CorsBuilder($response, 'http://www.example.com');
  35. $this->assertSame($builder, $builder->allowOrigin('*.example.com'));
  36. $this->assertHeader('http://www.example.com', $builder->build(), 'Access-Control-Allow-Origin');
  37. }
  38. /**
  39. * test allowOrigin() with SSL
  40. */
  41. public function testAllowOriginSsl(): void
  42. {
  43. $response = new Response();
  44. $builder = new CorsBuilder($response, 'https://www.example.com', true);
  45. $this->assertSame($builder, $builder->allowOrigin('http://example.com'));
  46. $this->assertNoHeader($response, 'Access-Control-Allow-Origin');
  47. $response = new Response();
  48. $builder = new CorsBuilder($response, 'http://www.example.com', true);
  49. $this->assertSame($builder, $builder->allowOrigin('https://example.com'));
  50. $this->assertNoHeader($builder->build(), 'Access-Control-Allow-Origin');
  51. $response = new Response();
  52. $builder = new CorsBuilder($response, 'http://www.example.com');
  53. $this->assertSame($builder, $builder->allowOrigin('https://example.com'));
  54. $this->assertNoHeader($builder->build(), 'Access-Control-Allow-Origin');
  55. }
  56. public function testAllowMethods(): void
  57. {
  58. $response = new Response();
  59. $builder = new CorsBuilder($response, 'http://example.com');
  60. $builder->allowOrigin('*');
  61. $this->assertSame($builder, $builder->allowMethods(['GET', 'POST']));
  62. $this->assertHeader('GET, POST', $builder->build(), 'Access-Control-Allow-Methods');
  63. }
  64. public function testAllowCredentials(): void
  65. {
  66. $response = new Response();
  67. $builder = new CorsBuilder($response, 'http://example.com');
  68. $builder->allowOrigin('*');
  69. $this->assertSame($builder, $builder->allowCredentials());
  70. $this->assertHeader('true', $builder->build(), 'Access-Control-Allow-Credentials');
  71. }
  72. public function testAllowHeaders(): void
  73. {
  74. $response = new Response();
  75. $builder = new CorsBuilder($response, 'http://example.com');
  76. $builder->allowOrigin('*');
  77. $this->assertSame($builder, $builder->allowHeaders(['Content-Type', 'Accept']));
  78. $this->assertHeader('Content-Type, Accept', $builder->build(), 'Access-Control-Allow-Headers');
  79. }
  80. public function testExposeHeaders(): void
  81. {
  82. $response = new Response();
  83. $builder = new CorsBuilder($response, 'http://example.com');
  84. $builder->allowOrigin('*');
  85. $this->assertSame($builder, $builder->exposeHeaders(['Content-Type', 'Accept']));
  86. $this->assertHeader('Content-Type, Accept', $builder->build(), 'Access-Control-Expose-Headers');
  87. }
  88. public function testMaxAge(): void
  89. {
  90. $response = new Response();
  91. $builder = new CorsBuilder($response, 'http://example.com');
  92. $builder->allowOrigin('*');
  93. $this->assertSame($builder, $builder->maxAge(300));
  94. $this->assertHeader('300', $builder->build(), 'Access-Control-Max-Age');
  95. }
  96. /**
  97. * When no origin is allowed, none of the other headers should be applied.
  98. */
  99. public function testNoAllowedOriginNoHeadersSet(): void
  100. {
  101. $response = new Response();
  102. $builder = new CorsBuilder($response, 'http://example.com');
  103. $response = $builder->allowCredentials()
  104. ->allowMethods(['GET', 'POST'])
  105. ->allowHeaders(['Content-Type'])
  106. ->exposeHeaders(['X-CSRF-Token'])
  107. ->maxAge(300)
  108. ->build();
  109. $this->assertNoHeader($response, 'Access-Control-Allow-Origin');
  110. $this->assertNoHeader($response, 'Access-Control-Allow-Headers');
  111. $this->assertNoHeader($response, 'Access-Control-Expose-Headers');
  112. $this->assertNoHeader($response, 'Access-Control-Allow-Methods');
  113. $this->assertNoHeader($response, 'Access-Control-Allow-Authentication');
  114. $this->assertNoHeader($response, 'Access-Control-Max-Age');
  115. }
  116. /**
  117. * When an invalid origin is used, none of the other headers should be applied.
  118. */
  119. public function testInvalidAllowedOriginNoHeadersSet(): void
  120. {
  121. $response = new Response();
  122. $builder = new CorsBuilder($response, 'http://example.com');
  123. $response = $builder->allowOrigin(['http://google.com'])
  124. ->allowCredentials()
  125. ->allowMethods(['GET', 'POST'])
  126. ->allowHeaders(['Content-Type'])
  127. ->exposeHeaders(['X-CSRF-Token'])
  128. ->maxAge(300)
  129. ->build();
  130. $this->assertNoHeader($response, 'Access-Control-Allow-Origin');
  131. $this->assertNoHeader($response, 'Access-Control-Allow-Headers');
  132. $this->assertNoHeader($response, 'Access-Control-Expose-Headers');
  133. $this->assertNoHeader($response, 'Access-Control-Allow-Methods');
  134. $this->assertNoHeader($response, 'Access-Control-Allow-Authentication');
  135. $this->assertNoHeader($response, 'Access-Control-Max-Age');
  136. }
  137. /**
  138. * Helper for checking header values.
  139. *
  140. * @param string $expected The expected value
  141. * @param \Cake\Http\Response $response The Response object.
  142. * @param string $header The header key to check
  143. */
  144. protected function assertHeader($expected, Response $response, $header): void
  145. {
  146. $this->assertTrue($response->hasHeader($header), 'Header key not found.');
  147. $this->assertSame($expected, $response->getHeaderLine($header), 'Header value not found.');
  148. }
  149. /**
  150. * Helper for checking header values.
  151. *
  152. * @param \Cake\Http\Response $response The Response object.
  153. * @param string $header The header key to check
  154. */
  155. protected function assertNoHeader(Response $response, $header): void
  156. {
  157. $this->assertFalse($response->hasHeader($header), 'Header key was found.');
  158. }
  159. }