jquery.form和跨域请求
我很难尝试使用跨域请求制作 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
AJAX 请求无法跨域执行(UPD:不再正确,所有现代浏览器都支持 CORS),但您可以使用 JSONP 代替。虽然 JSONP 可以跨域工作,但它不能用于 POST 请求,并且您需要将表单的方法更改为
get
并使用此方法:上面的解决方案依赖于您的服务器以有效的 jsonp 响应,否则
success
处理程序将不会被执行。例如:response.write(request.callback + '(' + result.to_json + ')')最新版本的 jQuery 可以在没有
ajaxForm
插件的情况下序列化表单。如果您不需要文件上传,可以使用: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: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:我认为 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
您还可以使用本地代理 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.
经过多次战斗,我终于在阿列克谢的帮助下克服了这一点。这是我现在的解决方案:
Javascript(直接使用jquery,没有jquery.form):
对于Sinatra,我使用了 sinatra-jsonp gem。我使 get 操作返回“true”或“false”,具体取决于电子邮件是否可以发送(例如,对于无效的电子邮件地址)。
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):
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).