jquery.form和跨域请求

发布于 2024-10-18 12:46:04 字数 2933 浏览 3 评论 0原文

我很难尝试使用跨域请求制作 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 https://stackoverflow.com/questions/4351904/sinatra-options-http-verb
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 请求(未发送电子邮件)。

尽管如此,我尝试过的所有版本的 jquery 总是会触发 error 回调。我追踪到 $.ajax(...) 调用,所以我不确定这个问题是来自 jquery.form 还是 jquery 本身。

我尝试注销来自错误的信息:

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

Output on jquery 1.4.3 (after the OPTIONS & POST requests are sent, both status 200):

0
(empty string)

Output on jquery 1.5 (after OPTIONS returns with a 200 status; POST is never已发送)

302
error

我真的在这里迷路了。

  • 有没有一个插件可以处理这个问题?
  • 我在某处遗漏了什么吗?

任何帮助将不胜感激。

I'm having a hard time trying to make jquery.form with a cross-domain request. I'm having issues with Firefox and Chrome (didn't even try IE yet).

Explanation: my whole site is located inside http://www.mysite.com. However, my contact form is on another server, referenced by http://contact.mysite.com . I thought that putting it on a subdomain would sidestep the issues regarding cross-domain requests, but apparently it didn't. http://contact.mysite.com is implemented in Sinatra.

My javascript setup is nothing fancy. The form's action points to http://contact.mysite.com and the method is POST:

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

jquery.form is configured with an ajaxForm call:

$(document).ready(function() {

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

});

The first problem I encountered was with Firefox 3.5 - apparently it sends an OPTIONS request expecting an specific answer from the server. I used this question to configure my Sinatra app so it did what was expected (it seems that more recent versions of sinatra include an options verb):

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

# patch sinatra so it handles options requests - see https://stackoverflow.com/questions/4351904/sinatra-options-http-verb
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

With jquery 1.4.3, I saw on firebug an OPTIONS request followed by a POST request (status 200. The email was sent). With jquery 1.3.2 or 1.5, only the OPTIONS request was shown (the email was not sent).

Nevertheless, the error callback is always fired with all versions of jquery I tried. I traced that down to the $.ajax(...) call, so I'm not sure of whether this problem comes from jquery.form or jquery itself.

I tried logging out the information coming from the error:

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

Output on jquery 1.4.3 (after the OPTIONS & POST requests are sent, both with status 200):

0
(empty string)

Output on jquery 1.5 (after OPTIONS returns with a 200 status; POST is never sent)

302
error

I'm really lost here.

  • Is there a plugin that handles this?
  • Am I missing something somewhere?

Any help will be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不及他 2024-10-25 12:46:04

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
});

AJAX requests cannot be executed cross-domain (UPD: not true anymore, all modern browsers support CORS), but you can use JSONP instead. Although JSONP works cross-domain, it can't be used for POST requests, and you'll need to change you form's method to get and use this:

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

The solution above relies on your server responding with a valid jsonp response, otherwise success handler won't be executed. e.g: response.write(request.callback + '(' + result.to_json + ')')


Latest versions of jQuery can serialize forms without the ajaxForm plugin. If you don't need file uploads you can use this:

$('form').submit(function() {
  var url = $(this).attr('action')
  var params = $(this).serialize()
  $.getJSON(url + '?' + params + "&callback=?", function(data) {
    // success
  })
  return false
});
∞琼窗梦回ˉ 2024-10-25 12:46:04

我认为 JSONP 是唯一可以跨域的 AJAX 请求。

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

I think JSONP the only AJAX request which can cross domain.

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

_畞蕅 2024-10-25 12:46:04

您还可以使用本地代理 URL 来执行请求,因为服务器通常可以使用 HttpRequest 或 cURL 等进行跨域调用。因此,基本上,您使用 ajax 对本地域上的 URL 进行调用,然后将请求转发到跨域 URL,并将来自 HttpRequest/cURL 的响应在本地域的响应中传递回浏览器。

You can also use a local proxy URL to perform the request as servers can generally make cross-domain calls using something like HttpRequest or cURL. So basically you make a call using ajax to a URL on the local domain and then forward the request to the cross-domain URL and pass the response from the HttpRequest/cURL back to the browser in the response from the local domain.

花间憩 2024-10-25 12:46:04

经过多次战斗,我终于在阿列克谢的帮助下克服了这一点。这是我现在的解决方案:

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,我使用了 sinatra-jsonp gem。我使 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

After lots of fighting, I finally ended up conquering this, with the help of Alexey. Here's my solution, for now:

Javascript (using jquery directly, without 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;
  });
});

With Sinatra, I used the sinatra-jsonp gem. I make the get action return "true" or "false" depending on whether the emails can be sent or not (for example, for an invalid email address).

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文