Intereting Posts

Запрос HTTP OPTIONS на сайтах Azure не удается из-за CORS

Недавно я переместил наши серверы из 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 позволяют очень минимально контролировать.

Я решил опубликовать полное решение этой проблемы, поскольку уже предоставленные ответы (хотя и технически корректные) не работают в этом конкретном случае для меня. Хитрость заключалась в следующем:

1. Добавьте <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> 

2. Переопределите обработчик по умолчанию для PHP и удалите OPTIONSVerbHandler

Следующий шаг (решение, предоставленное @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> 

Взгляните на этот пост, чтобы узнать больше о внутренней работе.

3. Удалите все заголовки ответов, установленные через код приложения.

Это был последний кусок головоломки, которая вызывала большинство проблем. Поскольку 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 , поскольку вы можете просто создать его там, где вам нужно, без перенастройки вашего сервера.