jquery.form et requêtes interdomaines

J’ai du mal à faire jquery.form avec une requête interdomaine . J’ai des problèmes avec Firefox et Chrome (je n’ai même pas encore essayé IE).

Explication: tout mon site est situé à l’ adresse http://www.mysite.com . Cependant, mon formulaire de contact est sur un autre serveur, référencé par http://contact.mysite.com . Je pensais que le placer sur un sous-domaine éviterait les problèmes liés aux requêtes inter-domaines, mais apparemment, ce n’est pas le cas. http://contact.mysite.com est implémenté dans Sinatra .

Ma configuration javascript n’a rien d’extraordinaire. L’action du formulaire pointe sur http://contact.mysite.com et la méthode est POST:

jquery.form est configuré avec un appel ajaxForm :

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

Le premier problème que j’ai rencontré concernait Firefox 3.5 – apparemment, il envoie une requête OPTIONS dans l’attente d’une réponse spécifique du serveur. J’ai utilisé cette question pour configurer mon application Sinatra et elle a donc répondu à ce qui était attendu (il semble que les versions les plus récentes de Sinatra incluent un verbe options):

 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 

Avec jQuery 1.4.3, j’ai vu sur firebug une requête OPTIONS suivie d’une requête POST (statut 200. Le courrier électronique a été envoyé). Avec jquery 1.3.2 ou 1.5, seule la requête OPTIONS était affichée (le courrier électronique n’était pas envoyé).

Néanmoins, le rappel d’ error est toujours déclenché avec toutes les versions de jquery que j’ai essayées. J’ai retracé cela jusqu’à l’ $.ajax(...) . Je ne sais donc pas si ce problème provient de jquery.form ou de jquery lui-même.

J’ai essayé de déconnecter les informations provenant de l’erreur:

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

Sortie sur jQuery 1.4.3 (après l’envoi des demandes OPTIONS & POST, les deux ayant le statut 200):

 0 (empty ssortingng) 

Sortie sur jquery 1.5 (après que OPTIONS soit revenu avec le statut 200, le POST n’est jamais envoyé)

 302 error 

Je suis vraiment perdu ici.

  • Y at-il un plugin qui gère cela?
  • Est-ce que je manque quelque chose quelque part?

Toute aide est la bienvenue.

Les requêtes AJAX ne peuvent pas être exécutées sur plusieurs domaines ( UPD: plus vrai, tous les navigateurs modernes prennent en charge CORS ), mais vous pouvez utiliser JSONP à la place. Bien que JSONP fonctionne sur plusieurs domaines, il ne peut pas être utilisé pour les demandes POST et vous devrez changer la méthode de votre formulaire pour get et utiliser ceci:

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

La solution ci-dessus repose sur une réponse jsonp valide de votre serveur, sinon le gestionnaire de success ne sera pas exécuté. par exemple: response.write(request.callback + '(' + result.to_json + ')')


Les dernières versions de jQuery peuvent sérialiser des formulaires sans le plugin ajaxForm . Si vous n’avez pas besoin de télécharger des fichiers, vous pouvez utiliser ceci:

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

Je pense que JSONP est la seule requête AJAX capable de traverser un domaine.

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

Vous pouvez également utiliser une URL de proxy locale pour exécuter la demande car les serveurs peuvent généralement effectuer des appels entre domaines à l’aide de quelque chose comme HttpRequest ou cURL. Donc, en gros, vous appelez ajax vers une URL du domaine local, puis transférez la demande à l’URL entre domaines et transmettez la réponse de HttpRequest / cURL au navigateur dans la réponse du domaine local.

Après beaucoup de combats, j’ai finalement fini par vaincre ça, avec l’aide d’Alexey. Voici ma solution, pour l’instant:

Javascript (en utilisant jquery directement, sans 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; }); }); 

Avec Sinatra, j’ai utilisé le joyau Sinatra-jsonp . Je fais en sorte que l’action get renvoie “true” ou “false” selon que les e-mails peuvent être envoyés ou non (par exemple, pour une adresse e-mail non valide).

 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