jquery.form и междоменные запросы - PullRequest
3 голосов
/ 21 февраля 2011

Я с трудом пытаюсь сделать jquery.form с междоменным запросом. У меня проблемы с Firefox и Chrome (я даже не пробовал IE).

Объяснение: весь мой сайт находится внутри http://www.mysite.com. Однако моя контактная форма находится на другом сервере, на который ссылается http://contact.mysite.com. Я думал, что размещение его на поддомене обойдёт проблемы, связанные с междоменными запросами, но, очевидно, это не так. http://contact.mysite.com реализовано в Синатра .

Моя настройка JavaScript не является чем-то необычным. Действие формы указывает на http://contact.mysite.com, а метод POST:

<form id="contact" action="http://contact.mysite.com/" method="post">

jquery.form настроен на ajaxForm вызов:

$(document).ready(function() {

  $('#contact').ajaxForm({
    success: function() { $('#success').fadeIn("slow"); },
    error: function() {  $('#error').fadeIn("slow"); }
  });

});

Первая проблема, с которой я столкнулся, была с Firefox 3.5 - очевидно, он отправляет запрос OPTIONS, ожидая конкретного ответа от сервера. Я использовал этот вопрос для настройки моего приложения Sinatra, чтобы оно выполняло то, что ожидалось (кажется, что более поздние версии sinatra включают глагол параметров):

require 'rubygems'
require 'sinatra'
require 'pony'

# patch sinatra so it handles options requests - see /3218614/sinatra-optsii-http-glagol
configure do
  class << Sinatra::Base
    def options(path, opts={}, &block)
      route 'OPTIONS', path, opts, &block
    end
  end
  Sinatra::Delegator.delegate :options
end

# respond to options requests so that firefox can do cross-domain ajax requests
options '/' do
  response['Access-Control-Allow-Origin'] = '*'
  response['Access-Control-Allow-Methods'] = 'POST'
  response['Access-Control-Max-Age'] = '2592000'
end

post '/' do
  # use Pony to send an email
  Pony.mail(...)
end

В jquery 1.4.3 я увидел в firebug запрос OPTIONS, за которым последовал запрос POST (статус 200. Письмо отправлено). В jquery 1.3.2 или 1.5 отображался только запрос OPTIONS (электронное письмо не было отправлено).

Тем не менее, обратный вызов error всегда запускается со всеми версиями jquery, которые я пробовал. Я проследил это до вызова $.ajax(...), поэтому я не уверен, происходит ли эта проблема из jquery.form или из самого jquery.

Я попытался выйти из информации, полученной с ошибкой:

$('#contact').ajaxForm({
  success: function() { $('#success').fadeIn("slow"); },
  error: function(jqXHR, textStatus, errorThrown) {
    console.log(jqXHR.status);
    console.log(jqXHR.statusText);
  }
}); 

Вывод в jquery 1.4.3 (после отправки запросов OPTIONS & POST, оба со статусом 200):

0
(empty string)

Вывод в jquery 1.5 (после того, как OPTIONS возвращается со статусом 200; POST никогда не отправляется)

302
error

Я действительно потерян здесь.

  • Есть ли плагин, который обрабатывает это?
  • Я что-то упустил?

Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

8 голосов
/ 22 февраля 2011

AJAX-запросы не могут выполняться между доменами ( UPD: больше не соответствует действительности, все современные браузеры поддерживают CORS ), но вместо этого вы можете использовать JSONP.Хотя JSONP работает с несколькими доменами, его нельзя использовать для запросов POST, и вам нужно изменить метод формы на get и использовать его:

$('#contact').ajaxForm({
  success: function() { $('#success').fadeIn("slow"); },
  error: function() {  $('#error').fadeIn("slow"); },
  dataType: 'jsonp'
});

Решение, приведенное выше, зависит от вашегосервер отвечает корректным ответом jsonp, иначе обработчик success не будет выполнен.Например: response.write(request.callback + '(' + result.to_json + ')')


Последние версии jQuery могут сериализовать формы без плагина ajaxForm.Если вам не нужны загрузки файлов, вы можете использовать это:

$('form').submit(function() {
  var url = $(this).attr('action')
  var params = $(this).serialize()
  $.getJSON(url + '?' + params + "&callback=?", function(data) {
    // success
  })
  return false
});
1 голос
/ 26 февраля 2011

После долгих боев я наконец-то победил с помощью Алексея. Вот мое решение, на данный момент:

Javascript (с использованием jquery напрямую, без jquery.form):

$(document).ready(function() {
  $('#contact').submit(function() {
    $('#success').fadeOut("slow");
    $('#bademail').fadeOut("slow");

    var url = $(this).attr('action')
    var params = $(this).serialize()
    $.getJSON(url + '?' + params + "&callback=?", function(data) {
      if(data == true) { // success
        $('#success').fadeIn("slow");
        $('#contact')[0].reset();
      } else { // error
        $('#bademail').fadeIn("slow");
      }
    });

    return false;
  });
});

В Синатре я использовал камень sinatra-jsonp . Действие get возвращает «true» или «false» в зависимости от того, могут ли электронные письма отправляться или нет (например, для недействительного адреса электронной почты).

require 'rubygems'
require 'sinatra'
require 'sinatra/jsonp'
require 'pony'


get '/' do

  # check for blanks, etc
  return jsonp false unless fields_valid(params)

  Pony.mail(
    ...
  )

  return jsonp true

end
1 голос
/ 22 февраля 2011

Вы также можете использовать локальный URL-адрес прокси для выполнения запроса, поскольку серверы обычно могут совершать междоменные вызовы, используя что-то вроде HttpRequest или cURL. Таким образом, в основном вы делаете вызов с помощью ajax на URL-адрес в локальном домене, а затем перенаправляете запрос на междоменный URL-адрес и передаете ответ из HttpRequest / cURL обратно в браузер в ответе из локального домена.

1 голос
/ 21 февраля 2011

Я думаю, что JSONP - единственный AJAX-запрос, который может проходить через домен.

http://en.wikipedia.org/wiki/JSON#JSONP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...