2009-07-27 8 views
4

L'arrière-plan est que j'ai un serveur de jobs distribué par celery configuré avec une vue Django qui retourne le statut d'un travail en cours d'exécution dans JSON. Le serveur de travaux est situé à celeryserver.mydomain.com et la page que j'exécute le jQuery est www.mondomaine.com donc je ne devrais pas avoir besoin de considérer JSONP pour cela je devrais, comme les demandes ne sont pas faites à différents domaines?Le rappel jQuery getJSON ne fonctionne pas - même avec JSON valide - et semble utiliser la requête "OPTION" pas "GET"

En regardant mes journaux de serveur, je vois que jQuery exécute l'appel getJSON toutes les 3 secondes comme il se doit (avec le setInterval Javascript). Il semble utiliser une requête OPTION, mais j'ai confirmé en utilisant curl que le JSON est toujours renvoyé pour ces types de requêtes.

Le problème est que l'appel Firebug console.log() dans le jQuery ci-dessous ne semble jamais exécuter! Celui avant l'appel getJSON. Ne pas avoir un travail de rappel est un problème pour moi parce que j'espérais faire un sondage pour un statut de travail de céleri de cette manière et faire diverses choses en fonction de l'état du travail.

<script type="text/javascript"> 
    var job_id = 'a8f25420-1faf-4084-bf45-fe3f82200ccb'; 

    // wait for the DOM to be loaded then start polling for conversion status 
    $(document).ready(function() { 
     var getConvertStatus = function(){ 
      console.log('getting some status'); 
      $.getJSON("https://celeryserver.mydomain.com/done/" + job_id, 
       function(data){ 
        console.log('callback works'); 
       }); 
     } 
     setInterval(getConvertStatus, 3000); 
    }); 
</script> 

Je l'ai utilisé curl pour vous assurer de ce que je reçois du serveur:

$ curl -D - -k -X GET https://celeryserver.mydomain.com/done/a8f25420-1faf-4084-bf45-fe3f82200ccb 
HTTP/1.1 200 OK 
Server: nginx/0.6.35 
Date: Mon, 27 Jul 2009 06:08:42 GMT 
Content-Type: application/json 
Transfer-Encoding: chunked 
Connection: close 

{"task": {"executed": true, "id": "a8f25420-1faf-4084-bf45-fe3f82200ccb"}} 

Ce JSON semble bien pour moi et JSONlint.com valide pour moi en ce moment .. J'ai aussi simulé la requête jQuery avec -X OPTION et j'ai récupéré exactement les mêmes données du serveur qu'avec un GET (type de contenu d'application/json etc.)

Je regarde cela depuis des lustres, aide grandement appréciée. Je suis un nouvel utilisateur de jQuery, mais cela ne devrait pas poser de problèmes, donc je n'ai aucune idée de ce que je fais de mal!

+0

Hey Mark! Je suis très intéressé par le code frontal que vous avez écrit pour cela car j'ai voulu écrire une partie javascript générique de céleri. Toutes les pensées et le code que vous avez à partager sont les bienvenus. – asksol

Répondre

3

Je pense que vous avez une question transversale sous-domaine, sub.domain.tld et domain.ltd ne sont pas les mêmes.

je vous recommande d'installer Firebug et vérifier si votre code est de lancer une Autorisation refusée Exception lorsque la demande commence, si c'est le cas, allez JSONP ...

0

Récupérez-vous le JSON d'un autre domaine? Si c'est le cas, vous êtes probablement confronté à des problèmes inter-domaines. Vous devrez utiliser JSONP. jQuery le fait automatiquement, mais le serveur doit le savoir.

Voir:

http://www.ibm.com/developerworks/library/wa-aj-jsonp1/

+0

Non, même domaine; la page avec jQuery est fournie à partir de www.mondomaine.com et l'appel getJSON récupère JSON à partir de xyz.mydomain.com – markhellewell

+3

Cela compte comme domaine séparé - les politiques interdomaines entrent en jeu même sur différents sous-domaines. – thedz

1

changer votre URL pour quelque chose comme:

"https://celeryserver.mydomain.com/done/" + ID_travail + "? Callback =?"

puis sur le résultat de votre vue django devrait être quelque chose à l'effet de:

'{callback}({json})'.format(callback=request.GET['callback'], json=MyJSON) 

... il y a probablement beaucoup de façons de faire cette dernière ligne, mais lu essentiellement dans le paramètre de rappel (ou nommez-le comme vous voulez)

puis de le renvoyer en appelant votre objet json (jQuery prend en charge la création d'une fonction de rappel (elle remplace '?'Avec la fonction générée))

1

Comme plusieurs personnes ont déclaré, sous-domaines comptent comme des domaines et j'ai eu un problème inter-domaines :)

Je l'ai résolu en créant un petit morceau de Django Middleware qui change la réponse de mes vues si elles retournent JSON et la demande avait un rappel attaché.

class JSONPMiddleware: 
    def process_response(self, request, response): 
     ctype = response.get('content-type', None) 
     cback = request.GET.get('callback', None) 

     if ctype == 'application/json' and cback: 
      jsonp = '{callback}({json})'.format(callback=cback, json=response.content) 
      return HttpResponse(content=jsonp, mimetype='application/javascript') 
     return response 

Tout fonctionne maintenant comme prévu. Merci!

Questions connexes