в jQuery $.Аякс.$ ,)(отправить отправку "параметры" как метод запроса в Firefox

возникли проблемы с тем, что я думал, был относительно простым плагином jQuery...

плагин должен получать данные из php-скрипта через ajax, чтобы добавить параметры в <select>. Запрос ajax довольно общий:

$.ajax({
  url: o.url,
  type: 'post',
  contentType: "application/x-www-form-urlencoded",
  data: '{"method":"getStates", "program":"EXPLORE"}',
  success: function (data, status) {
    console.log("Success!!");
    console.log(data);
    console.log(status);
  },
  error: function (xhr, desc, err) {
    console.log(xhr);
    console.log("Desc: " + desc + "\nErr:" + err);
  }
});

это, кажется, отлично работает в Safari. В Firefox 3.5,REQUEST_TYPE на сервере всегда есть "параметры", а данные $_POST не отображаются. Apache регистрирует запрос как тип "параметры":

::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46

почему этот вызов ajax работает в Safari, но не Firefox, и как это исправить для Firefox?

Response Headers
Date: Wed, 08 Jul 2009 21:22:17 GMT
Server:Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2
X-Powered-By: PHP/5.2.6
Content-Length  46
Keep-Alive  timeout=15, max=100
Connection  Keep-Alive
Content-Type    text/html

Request Headers
Host    orderform:8888
User-Agent  Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive  300
Connection  keep-alive
Origin  http://ux.inetu.act.org
Access-Control-Request-Method   POST
Access-Control-Request-Headers  x-requested-with

вот изображение выхода Firebug:

23 ответов


причиной ошибки является та же политика происхождения. Это только позволяет делать XMLHTTPRequests в свой собственный домен. Посмотрите, можете ли вы использовать JSONP обратного вызова вместо:

$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );

я использовал следующий код на стороне Django для интерпретации запроса опций и установки необходимых заголовков управления доступом. После этого мои междоменные запросы от Firefox начали работать. Как уже говорилось ранее, браузер сначала отправляет запрос параметров, а затем сразу после этого POST / GET

def send_data(request):
    if request.method == "OPTIONS": 
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
        response['Access-Control-Max-Age'] = 1000
        # note that '*' is not valid for Access-Control-Allow-Headers
        response['Access-Control-Allow-Headers'] = 'origin, x-csrftoken, content-type, accept'
        return response
    if request.method == "POST":
        # ... 

Edit: похоже, что, по крайней мере, в некоторых случаях вам также нужно добавить те же заголовки управления доступом к фактическому ответу. Это может быть немного запутанным, так как запрос кажется успешным, но Firefox не передает содержимое ответа на Javascript.


этой mozilla developer center статья описывает различные сценарии междоменных запросов. В статье, по-видимому, указано, что запрос POST с типом контента "application/x-www-form-urlencoded" должен быть отправлен как "простой запрос" (без запроса параметров "preflight"). Однако я обнаружил , что Firefox отправил запрос опций, хотя мой пост был отправлен с этим типом контента.

Я смог сделать эту работу, создав обработчик запросов опций на сервер, который установил заголовок ответа "Access-Control-Allow-Origin "в"*". Вы можете быть более ограничительными, установив его на что-то конкретное, например'http://someurl.com'. Кроме того, я читал, что, предположительно, вы можете указать разделенный запятыми список нескольких источников, но я не мог заставить это работать.

Как только Firefox получает ответ на запрос опций с приемлемым значением "Access-Control-Allow-Origin", он отправляет запрос POST.


я исправил эту проблему, используя полностью основанное на Apache решение. В моем vhost / htaccess я поставил следующий блок:

# enable cross domain access control
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"

# force apache to return 200 without executing my scripts
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]

вам может не понадобиться последняя часть, в зависимости от того, что произойдет, когда Apache выполнит ваш целевой скрипт. Заслуга дружелюбный народ ServerFault для последней части.


этот PHP в верхней части отвечающего скрипта, похоже, работает. (С Firefox 3.6.11. Я еще не провел много тестов.)

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
if(array_key_exists('HTTP_ACCESS_CONTROL_REQUEST_HEADERS', $_SERVER)) {
    header('Access-Control-Allow-Headers: '
           . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
} else {
    header('Access-Control-Allow-Headers: *');
}

if("OPTIONS" == $_SERVER['REQUEST_METHOD']) {
    exit(0);
}

У меня была такая же проблема с отправкой запросов на Google maps, и решение довольно простое с jQuery 1.5 - для использования типа данных dataType: "jsonp"


Culprit является предполетным запросом с использованием метода OPTIONS

для HTTP-запросов методами, которые могут вызвать побочные эффекты данных Пользователя (в частности, для HTTP-методов GET или после использования определенных типов MIME), спецификация предписывает, что браузеры "предполетный" просьба, упрашивание поддерживаемых методов с сервера с помощью HTTP-параметров запроса метода, а затем, после "одобрения" от сервера, отправляет сам запрос с фактической HTTP-запроса метод.

веб-спецификация см.:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Я решил проблему, добавив следующие строки в nginx conf.

    location / {
               if ($request_method = OPTIONS ) {
                   add_header Access-Control-Allow-Origin  "*";
                   add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS";
                   add_header Access-Control-Allow-Headers "Authorization";
                   add_header Access-Control-Allow-Credentials  "true";
                   add_header Content-Length 0;
                   add_header Content-Type text/plain;
                   return 200;
               }
    location ~ ^/(xxxx)$ {
                if ($request_method = OPTIONS) {
                    rewrite ^(.*)$ / last;
                }
    }

Я просматривал источник 1.3.2, при использовании JSONP запрос выполняется путем динамического создания элемента скрипта, который проходит через браузеры политики того же домена. Естественно, вы не можете сделать запрос POST с помощью элемента скрипта, браузер получит результат с помощью GET.

при запросе вызова JSONP элемент SCRIPT не генерируется, поскольку он делает это только тогда, когда тип вызова AJAX установлен в ПОЛУЧИТЬ.

http://dev.jquery.com/ticket/4690


У нас была такая проблема с ASP.Net - ... Наш IIS возвращал внутреннюю ошибку сервера при попытке выполнить jQuery $.post чтобы получить некоторый html-контент из-за PageHandlerFactory был ограничен, чтобы ответить только GET,HEAD,POST,DEBUG глаголы. Таким образом, вы можете изменить это ограничение, добавив глагол "параметры" в список или выбрав "все глаголы"

вы можете изменить это в Диспетчере IIS, выбрав свой веб-сайт, а затем выбрав сопоставления обработчиков, дважды щелкните в PageHandlerFactory для *.apx файлы, как вам нужно (мы используем интегрированный пул приложений с framework 4.0). Нажмите на запрос ограничений, затем перейдите к глаголам Tabn и примените свою модификацию.

Теперь наш!--0--> запрос работает, как ожидалось :)


проверьте, если ваша форма action URL включает в себя www часть домена, в то время как исходная страница, которую вы открыли, просматривается без www.

обычно выполняется для канонических URL-адресов..

я боролся в течение нескольких часов, прежде чем наткнулся на эту статью и нашел намек на кросс-домен.


мне кажется, что если o.url = 'index.php' и этот файл существует в порядке и возвращает сообщение об успехе в консоли. Он возвращает ошибку, если я использую url:http://www.google.com

Если вы делаете запрос post, почему бы не использовать непосредственно $.пост способ:

$.post("test.php", { func: "getNameAndTime" },
    function(data){
        alert(data.name); // John
        console.log(data.time); //  2pm
    }, "json");

Это намного проще.


Я опубликовал четкий пример того, как решить эту проблему, если контролировать код сервера домена, который вы публикуете. Этот ответ затрагивается в этой теме, но это более четко объясняет его IMO.

как отправить междоменный запрос POST через JavaScript?


решение:

  1. использовать тип данных: json
  2. добавить &callback=? на Ваш url

это работало на вызове API Facebook и с Firefox. Firebug это с помощью GET вместо OPTIONS с вышеуказанными условиями (оба из них).


еще одна возможность обойти проблему-использовать прокси-скрипт. Этот метод описан для пример


можете ли вы попробовать это без

contentType:application/x-www-form-urlencoded


попробуйте добавить опцию:

тип данных:"json"


 function test_success(page,name,id,divname,str)
{ 
 var dropdownIndex = document.getElementById(name).selectedIndex;
 var dropdownValue = document.getElementById(name)[dropdownIndex].value;
 var params='&'+id+'='+dropdownValue+'&'+str;
 //makerequest_sp(url, params, divid1);

 $.ajax({
    url: page,
    type: "post",
    data: params,
    // callback handler that will be called on success
    success: function(response, textStatus, jqXHR){
        // log a message to the console
        document.getElementById(divname).innerHTML = response;

        var retname = 'n_district';
        var dropdownIndex = document.getElementById(retname).selectedIndex;
        var dropdownValue = document.getElementById(retname)[dropdownIndex].value;
        if(dropdownValue >0)
        {
            //alert(dropdownValue);
            document.getElementById('inputname').value = dropdownValue;
        }
        else
        {
            document.getElementById('inputname').value = "00";
        }
        return;
        url2=page2; 
        var params2 = parrams2+'&';
        makerequest_sp(url2, params2, divid2);

     }
});         
}

У меня была аналогичная проблема с попыткой использовать API Facebook.

единственным contentType, который не отправил предварительный запрос, казалось, был просто text/plain... не остальные параметры, упомянутые в Mozilla здесь

  • почему это единственный браузер, который делает это?
  • почему Facebook не знает и не принимает запрос предполетной подготовки?

FYI: вышеупомянутый moz doc предлагает заголовки X-Lori должны триггер запроса Preflighted ... это не так.


вам нужно сделать некоторую работу на стороне сервера. Я вижу, что вы используете PHP на стороне сервера, но решение для веб-приложения .NET здесь: Не удается установить тип содержимого в "application / json" в jQuery.ajax

сделайте то же самое в PHP-скрипте, и он будет работать. Просто: при первом запросе браузер запрашивает сервер, разрешено ли отправлять такие данные с таким типом, а второй запрос является правильным/разрешенным.


попробуйте добавить следующее:

dataType: "json",
ContentType: "application/json",
data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}),  

я использовал url-адрес прокси для решения аналогичной проблемы, когда я хочу опубликовать данные на моем Apache solr, размещенном на другом сервере. (Возможно, это не идеальный ответ, но он решает мою проблему.)

следуйте по этому URL:использование Mode-Rewrite для проксирования, я добавляю эту строку в свой httpd.conf:

 RewriteRule ^solr/(.*)$ http://ip:8983/solr [P]

поэтому я могу просто публиковать данные в /solr вместо публикации данных в http://ip:8983/solr/*. Тогда он будет размещать данные в том же источнике.


у меня уже есть этот код, хорошо обрабатывающий мою ситуацию cors в php:

header( 'Access-Control-Allow-Origin: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Headers: '.CMSConfig::ALLOW_DOMAIN );
header( 'Access-Control-Allow-Credentials: true' );

и он работал нормально локально и удаленно, но не для загрузки, когда удаленный.

что-то происходит с apache/php или моим кодом, я не потрудился его искать, когда вы запрашиваете параметры, он возвращает мой заголовок с правилами cors, но с результатом 302. Поэтому мой браузер не признает приемлемой ситуации.

то, что я сделал, основываясь на ответе @Mark McDonald, просто поставлено этот код после моего заголовка:

if( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' )
{
    header("HTTP/1.1 202 Accepted");
    exit;
}

Теперь, при запросе OPTIONS Он просто отправит заголовок и результат 202.


обратите внимание:

JSONP поддерживает только метод запроса GET.

*отправить запрос в Firefox:*

$.ajax({
   type: 'POST',//<<===
   contentType: 'application/json',
   url: url,
   dataType: "json"//<<=============
    ...
});

запрос отправить по опции(while ==> введите: 'POST')!!!!

$.ajax({
    type: 'POST',//<<===
    contentType: 'application/json',
    url: url,
    dataType: "jsonp"//<<==============
    ...
});

но выше запрос отправить по GET(while ==> введите: 'POST')!!!!

когда вы находитесь в "кросс-домена общение", будьте внимательны и осторожны.