Недавно я переместил наши серверы из Rackspace CloudSites (работает на Apache / Linux) на веб-сайты Windows Azure. С момента миграции все запросы JQuery AJAX в нашем REST API начали сбой из-за CORS.
Мы используем пользовательские заголовки, поэтому jQuery делает запрос перед полетом HTTP OPTIONS перед запуском фактических вызовов API. Проблема заключается в том, что запрос OPTIONS, похоже, не достигает моего PHP-кода и вместо этого возвращается каким-либо другим объектом (очевидно, веб-сервером), который, как мне кажется, не контролируется.
Я использую следующие заголовки уже пару лет, поэтому я уверен, что проблема не в PHP-коде:
<?php $this->output->set_header("Access-Control-Allow-Origin: *"); $this->output->set_header("Access-Control-Allow-Methods: GET,POST,DELETE,HEAD,PUT,OPTIONS"); $this->output->set_header("Access-Control-Allow-Headers: X-Olaround-Debug-Mode, Authorization, Accept"); $this->output->set_header("Access-Control-Expose-Headers: X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" ); ?>
Я предполагаю, что проблема связана с сайтами Azure, поскольку код, похоже, отлично работает на моей машине разработки (Windows 8 / IIS 8.0). Я новичок в Azure (и в Windows-хостинге в целом), поэтому я почти не знаю, как подойти и отладить эту проблему, поскольку веб-сайты Azure позволяют очень минимально контролировать.
Я решил опубликовать полное решение этой проблемы, поскольку уже предоставленные ответы (хотя и технически корректные) не работают в этом конкретном случае для меня. Хитрость заключалась в следующем:
<customHeaders>
в <httpProtocol>
в web.config Подобно @hcoat, также предложенному выше, добавление system.webServer.httpProtocol.customHeaders
было первым шагом для решения проблемы (я уже пробовал это самостоятельно раньше, но это не сработало). Добавьте все настраиваемые заголовки и методы HTTP, которые необходимо установить для CORS.
<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="GET,POST,DELETE,HEAD,PUT,OPTIONS" /> <add name="Access-Control-Allow-Headers" value="Origin, X-Olaround-Debug-Mode, Authorization, Accept" /> <add name="Access-Control-Expose-Headers" value="X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" /> </customHeaders> </httpProtocol>
Следующий шаг (решение, предоставленное @Bing Han), заключается в удалении стандартного OPTIONSVerbHandler
определенного в IIS, а также для установки специального обработчика PHP54_via_FastCGI
который принимает ваши дополнительные HTTP-методы. Обработчик по умолчанию работает только с запросами GET, POST и HEAD.
<handlers> <remove name="OPTIONSVerbHandler" /> <remove name="PHP54_via_FastCGI" /> <add name="PHP54_via_FastCGI" path="*.php" verb="GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK" modules="FastCgiModule" scriptProcessor="D:\Program Files (x86)\PHP\v5.4\php-cgi.exe" resourceType="Either" requireAccess="Script" /> </handlers>
Взгляните на этот пост, чтобы узнать больше о внутренней работе.
Это был последний кусок головоломки, которая вызывала большинство проблем. Поскольку IIS уже добавлял <customHeaders>
, фрагмент кода PHP, который я использовал в вышеперечисленном вопросе, дублировал их. Это вызвало проблемы на уровне браузера, которые плохо реагировали на несколько заголовков того же типа.
web.config
который работал для этой проблемы <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Imported Rule 1" stopProcessing="true"> <match url="^(.*)$" ignoreCase="false" /> <conditions logicalGrouping="MatchAll"> <add input="{R:1}" pattern="^(dir_path\.php|lolaround|lolaround\.php|app_assets)" ignoreCase="false" negate="true" /> </conditions> <action type="Rewrite" url="lolaround.php/{R:1}" /> </rule> <rule name="Imported Rule 2" stopProcessing="true"> <match url="lolaround/(.*)" ignoreCase="false" /> <action type="Rewrite" url="/lolaround.php/{R:1}" /> </rule> </rules> </rewrite> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="GET,POST,DELETE,HEAD,PUT,OPTIONS" /> <add name="Access-Control-Allow-Headers" value="Origin, X-Olaround-Debug-Mode, Authorization, Accept" /> <add name="Access-Control-Expose-Headers" value="X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" /> </customHeaders> </httpProtocol> <handlers> <remove name="OPTIONSVerbHandler" /> <remove name="PHP54_via_FastCGI" /> <add name="PHP54_via_FastCGI" path="*.php" verb="GET, PUT, POST, HEAD, OPTIONS, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK" modules="FastCgiModule" scriptProcessor="D:\Program Files (x86)\PHP\v5.4\php-cgi.exe" resourceType="Either" requireAccess="Script" /> </handlers> </system.webServer> </configuration>
Примечание . Хотя ответы на вопросы @hcoat и @Bing Han были полезны в этой проблеме, я могу присудить награду только одному из них. Я решил отдать его @Bing Han, потому что его ответ приблизил меня к решению (и я не смог найти способ добавить собственный обработчик PHP из собственного поиска).
Обновление : я отредактировал ответ, чтобы добавить поддержку метода HTTP DELETE, который отсутствовал в исходном ответе.
Запрос HTTP OPTIONS завершается с ошибкой, потому что обработчик PHP-CGI по умолчанию не обрабатывает глагол « OPTIONS
».
Добавьте следующий код в файл web.config
чтобы решить проблему.
<configuration> <system.webServer> <!-- Some other settings --> <handlers> <remove name="OPTIONSVerbHandler" /> <remove name="PHP54_via_FastCGI" /> <add name="PHP54_via_FastCGI" path="*.php" verb="GET,HEAD,POST,OPTIONS" modules="FastCgiModule" scriptProcessor="D:\Program Files (x86)\PHP\v5.4\php-cgi.exe" resourceType="Either" /> </handlers> </system.webServer> </configuration>
У меня есть сообщение в блоге об этом: http://tekblg.blogspot.sg/2013/09/azure-websites-php-cross-domain-request.html
На сервере Windows вы не можете полагаться на заголовки php для CORS. Вам необходимо создать web.config
в корне сайта или корневом каталоге приложения, содержащем что-то вроде следующего.
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="GET,POST,DELETE,HEAD,PUT,OPTIONS" /> <add name="Access-Control-Allow-Headers" value="X-Olaround-Debug-Mode, Authorization, Accept" /> <add name="Access-Control-Expose-Headers" value="X-Olaround-Debug-Mode, X-Olaround-Request-Start-Timestamp, X-Olaround-Request-End-Timestamp, X-Olaround-Request-Time, X-Olaround-Request-Method, X-Olaround-Request-Result, X-Olaround-Request-Endpoint" /> </customHeaders> </httpProtocol> </system.webServer> </configuration>
Этот процесс сопоставим с настройкой файла .htaccess
, поскольку вы можете просто создать его там, где вам нужно, без перенастройки вашего сервера.