Как пропустить предпечатный запрос OPTIONS?

Я разработал приложение PhoneGap, которое теперь трансформируется на мобильный сайт. Все работает плавно, кроме одного небольшого сбоя. Я использую определенный сторонний API через запрос POST, который отлично работает в приложении, но не работает в версии мобильного сайта.

После более близкого взгляда кажется, что AngularJS (я предполагаю, что браузер фактически) сначала отправляет запрос OPTIONS. Сегодня я много узнал о CORS, но я не могу понять, как полностью отключить его. У меня нет доступа к этому API (так что изменения на этой стороне невозможны), но они добавили домен, над которым я работаю, в заголовок Access-Control-Allow-Origin.

Это код, о котором я говорю:

        var request = {
                language: 'fr',
                barcodes: [
                    {
                        barcode: 'somebarcode',
                        description: 'Description goes here'
                    }
                ]
            };
        }
        var config = {
            headers: { 
                'Cache-Control': 'no-cache',
                'Content-Type': 'application/json'
            }
        };
        $http.post('http://somedomain.be/trackinginfo', request, config).success(function(data, status) {
            callback(undefined, data);
        }).error(function(data, status) {
            var err = new Error('Error message');
            err.status = status;
            callback(err);
        });

Как я могу запретить браузеру (или AngularJS) отправлять этот запрос OPTIONS и просто перейти к фактическому запросу POST? Я использую AngularJS 1.2.0.

Спасибо заранее.

Ответ 1

Предпечатная проверка запускается вашим типом контента application/json. Самый простой способ предотвратить это - установить тип содержимого в вашем случае text/plain. Типы содержимого application/x-www-form-urlencoded & multipart/form-data также допустимы, но вам, конечно, необходимо соответствующим образом отформатировать полезную нагрузку запроса.

Если после внесения этого изменения вы все еще видите предполетную проверку, то Angular также может добавить X-заголовок к запросу.

Или у вас могут быть заголовки (Authorization, Cache-Control...), которые будут его запускать, смотрите:

Ответ 2

Как сказал Рэй, вы можете остановить его, изменив заголовок контента, например -

 $http.defaults.headers.post["Content-Type"] = "text/plain";

Пример -

angular.module('myApp').factory('User', ['$resource','$http',
    function($resource,$http){
        $http.defaults.headers.post["Content-Type"] = "text/plain";
        return $resource(API_ENGINE_URL+'user/:userId', {}, {
            query: {method:'GET', params:{userId:'users'}, isArray:true},
            getLoggedIn:{method:'GET'}
        });
    }]);

Или прямо на вызов -

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'text/plain'
 },
 data: { test: 'test' }
}

$http(req).then(function(){...}, function(){...});

Это не будет отправлять запрос на предварительный рейс.

ПРИМЕЧАНИЕ.. Запрос не должен иметь никакого настраиваемого параметра заголовка. Если заголовок запроса содержит любой пользовательский заголовок, браузер сделает запрос перед полетом, вы не можете его избежать.

Ответ 3

Я думаю, что лучший способ - проверить, является ли запрос типа "ОПЦИИ" возвратом 200 из средней посуды. Это сработало для меня.

express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });

Ответ 4

При выполнении определенных типов междоменных запросов AJAX современные браузеры, которые поддерживают CORS, вставляют дополнительный запрос "предполетной проверки", чтобы определить, имеют ли они разрешение на выполнение действия. Из примера запроса:

$http.get( ‘https://example.com/api/v1/users/’ +userId,
  {params:{
           apiKey:’34d1e55e4b02e56a67b0b66’
          }
  } 
);

В результате этого фрагмента мы видим, что адрес был отправлен двумя запросами (OPTIONS и GET). Ответ с сервера включает заголовки, подтверждающие допустимость запроса GET. Если ваш сервер не настроен на правильное выполнение запроса OPTIONS, запросы клиента не будут выполнены. Например:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: POST
Access-Control-Allow-Orgin: *
Access-Control-Max-Age: 172800
Allow: PUT
Allow: OPTIONS
Allow: POST
Allow: DELETE
Allow: GET

Ответ 5

Вам нужно изменить в двух файлах. 1 - Сначала в файле web.config клиента добавьте тег под тегом system.webserver

<httpProtocol>
         <customHeaders>
           <add name="Access-Control-Allow-Origin" value="*"/>
           <add name="Access-Control-Allow-Headers" value="Content-Type" />
           <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, 
             DELETE, OPTIONS" />
         </customHeaders>
</httpProtocol>

2 - В файле сервера Global.asax

protected void Application_BeginRequest()      {          if (Request.Headers.AllKeys.Contains( "Origin" ) && Request.HttpMethod == "ОПЦИИ" )          {              Response.Flush,();          }      }

Ответ 6

Preflight - это функция веб-безопасности, реализованная браузером. Для Chrome вы можете отключить всю веб-безопасность, добавив флаг --disable-web-security.

Например: "C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir = "C:\newChromeSettingsWithoutSecurity". Вы можете сначала создать новый ярлык Chrome, перейти к его свойствам и изменить цель, как указано выше. Это должно помочь!

Ответ 7

настройка типа содержимого на undefined заставит javascript передавать данные заголовка. Так же, как и над созданием конфигураций заголовков angular $httpProvider по умолчанию. Angular $http Документация

$http({url:url,method:"POST", headers:{'Content-Type':undefined}).then(success,failure);