我很难尝试使用跨域请求制作jquery.form。我遇到了Firefox和Chrome的问题(甚至还没试过IE)。
说明:我的整个网站都位于http://www.mysite.com内。但是,我的联系表单位于另一台服务器上,由http://contact.mysite.com引用。我认为将它放在子域上会避开有关跨域请求的问题,但显然它没有。 http://contact.mysite.com已在Sinatra中实施。
我的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请求,期望来自服务器的特定答案。我使用this question来配置我的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&amp; POST请求后,状态为200):
0
(empty string)
jquery 1.5上的输出(在OPTIONS返回200状态后;永远不发送POST)
302
error
我真的迷失在这里。
非常感谢任何帮助。
答案 0 :(得分:8)
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 :(得分:1)
我认为JSONP是唯一可以跨域的AJAX请求。
答案 2 :(得分:1)
您还可以使用本地代理URL来执行请求,因为服务器通常可以使用HttpRequest或cURL等方式进行跨域调用。所以基本上你使用ajax调用本地域上的URL,然后将请求转发到跨域URL,并将来自HttpRequest / cURL的响应传递回本地域响应中的浏览器。
答案 3 :(得分:1)
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