diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 4187c3b..85093e7 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.33 under development ------------------------ +- Bug #17878: Detect CORS AJAX requests without `X-Requested-With` in `Request::getIsAjax()` (dicrtarasov, samdark) - Enh #17929: Actions can now have bool typed params bound (alex-code) - Enh #17827: Add `StringValidator::$strict` that can be turned off to allow any scalars (adhayward, samdark) - Bug #16145: Fix `Html` helper `checkboxList()`, `radioList()`, `renderSelectOptions()`, `dropDownList()`, `listBox()` methods to work properly with traversable selection (samdark) diff --git a/framework/web/Request.php b/framework/web/Request.php index 834a52e..95ef8e5 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -471,8 +471,8 @@ class Request extends \yii\base\Request /** * Returns whether this is an AJAX (XMLHttpRequest) request. * - * Note that jQuery doesn't set the header in case of cross domain - * requests: https://stackoverflow.com/questions/8163703/cross-domain-ajax-doesnt-send-x-requested-with-header + * Note that in case of cross domain requests, browser doesn't set the X-Requested-With header by default: + * https://stackoverflow.com/questions/8163703/cross-domain-ajax-doesnt-send-x-requested-with-header * * In case you are using `fetch()`, pass header manually: * @@ -487,7 +487,13 @@ class Request extends \yii\base\Request */ public function getIsAjax() { - return $this->headers->get('X-Requested-With') === 'XMLHttpRequest'; + $origin = $this->headers->get('Origin'); + + return + ($this->headers->get('X-Requested-With') === 'XMLHttpRequest') || + ($this->headers->get('Sec-Fetch-Mode') === 'cors') || + ($this->headers->get('Sec-Fetch-Site') === 'cross-site') || + ($origin !== null && $origin !== $this->getHostInfo()); } /** diff --git a/tests/framework/ChangeLogTest.php b/tests/framework/ChangeLogTest.php index fe03215..08d9850 100644 --- a/tests/framework/ChangeLogTest.php +++ b/tests/framework/ChangeLogTest.php @@ -18,7 +18,7 @@ class ChangeLogTest extends TestCase public function changeProvider() { - $lines = explode("\n", file_get_contents(__DIR__ . '/../../framework/CHANGELOG.md')); + $lines = preg_split("~\R~", file_get_contents(__DIR__ . '/../../framework/CHANGELOG.md'), PREG_SPLIT_NO_EMPTY); // Don't check last 1500 lines, they are old and often don't obey the standard. $lastIndex = count($lines) - 1500; diff --git a/tests/framework/web/RequestTest.php b/tests/framework/web/RequestTest.php index 934148b..af7770b 100644 --- a/tests/framework/web/RequestTest.php +++ b/tests/framework/web/RequestTest.php @@ -908,6 +908,24 @@ class RequestTest extends TestCase ], true, ], + [ + [ + 'HTTP_Sec-Fetch-Mode' => 'cors', + ], + true, + ], + [ + [ + 'HTTP_Sec-Fetch-Site' => 'cross-site', + ], + true, + ], + [ + [ + 'HTTP_Origin' => 'https://example.com/', + ], + true, + ], ]; }