javascript jquery.form 和跨域请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5066213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:49:44  来源:igfitidea点击:

jquery.form and cross-domain requests

javascriptjqueryajaxjquery-pluginscross-domain

提问by kikito

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

我很难尝试使用跨域请求制作jquery.form。我在使用 Firefox 和 Chrome 时遇到了问题(甚至还没有尝试过 IE)。

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.comis implemented in Sinatra.

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

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

我的 javascript 设置没什么特别的。表单的操作指向http://contact.mysite.com,方法是 POST:

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

jquery.form is configured with an ajaxFormcall:

jquery.form 配置了一个ajaxForm调用:

$(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 questionto configure my Sinatra app so it did what was expected (it seems that more recent versions of sinatra include an options verb):

我遇到的第一个问题是 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

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).

使用 jquery 1.4.3,我在 firebug 上看到一个 OPTIONS 请求,然后是一个 POST 请求(状态 200。电子邮件已发送)。对于 jquery 1.3.2 或 1.5,仅显示 OPTIONS 请求(未发送电子邮件)。

Nevertheless, the errorcallback 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.

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

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):

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

0
(empty string)

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

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

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.

任何帮助将不胜感激。

回答by Alexey Lebedev

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 getand use this:

AJAX 请求不能跨域执行(UPD:不再正确,所有现代浏览器都支持CORS),但您可以使用 JSONP 代替。虽然 JSONP 可以跨域工作,但它不能用于 POST 请求,您需要将表单的方法更改为get并使用:

$('#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 successhandler won't be executed. e.g: response.write(request.callback + '(' + result.to_json + ')')

上面的解决方案依赖于您的服务器以有效的 jsonp 响应进行响应,否则success将不会执行处理程序。例如:response.write(request.callback + '(' + result.to_json + ')')



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

最新版本的 jQuery 可以在没有ajaxForm插件的情况下序列化表单。如果你不需要文件上传,你可以使用这个:

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

回答by Mark Holland

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

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

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

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

回答by Rob

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.

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

回答by kikito

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):

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

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).

对于 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