jquery.form和跨域请求

我正在努力尝试使用跨域请求创建jquery.form 。 我遇到了Firefox和Chrome的问题(甚至还没试过IE)。

说明:我的整个站点位于http://www.mysite.com内 。 但是,我的联系表单位于另一台服务器上,由http://contact.mysite.com引用。 我认为将它放在子域上会避开有关跨域请求的问题,但显然它没有。 http://contact.mysite.com在Sinatra实施。

我的javascript设置没什么特别的。 表单的操作指向http://contact.mysite.com ,方法是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); } }); 

在jquery 1.4.3上输出(在发送OPTIONS和POST请求之后,状态为200):

 0 (empty string) 

在jquery 1.5上输出(在OPTIONS返回200状态后;永远不发送POST)

 302 error 

我真的迷失在这里。

  • 有没有一个插件来处理这个?
  • 我错过了某个地方的东西吗?

任何帮助将不胜感激。

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插件的ajaxForm序列化表单。 如果您不需要文件上传,可以使用:

 $('form').submit(function() { var url = $(this).attr('action') var params = $(this).serialize() $.getJSON(url + '?' + params + "&callback=?", function(data) { // success }) return false }); 

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

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

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

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

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-jsonpgem 。 我将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