web-dev-qa-db-fra.com

Publier des données sur JsonP

Est-il possible de publier des données sur JsonP? Ou est-ce que toutes les données doivent être passées dans la chaîne de requête en tant que requête GET?

J'ai beaucoup de données que je dois envoyer au service, cross domain, et il est trop gros pour envoyer via la chaîne de requête

Quelles sont les options pour contourner cela?

101
ChrisCa

Il n'est pas possible de faire un POST asynchrone sur un service situé dans un autre domaine, en raison de la limitation (tout à fait raisonnable) de même règle d'origine . JSON-P ne fonctionne que parce que vous êtes autorisé à insérer <script> balises dans le DOM, et elles peuvent pointer n’importe où.

Vous pouvez, bien sûr, faire d’une page d’un autre domaine l’action d’un formulaire POST de forme courante.

Edit : Il y en a hacks intéressants si vous êtes prêt à faire beaucoup d'efforts pour insérer des caractères cachés <iframe>s et se faufiler avec leurs propriétés.

82
friedo

Si vous devez envoyer beaucoup de données entre domaines. Je crée généralement un service que vous pouvez appeler en deux étapes:

  1. Le client commence par envoyer un formulaire (poste autorisé entre domaines). Le service stocke l'entrée dans la session sur le serveur (à l'aide de GUID en tant que clé). (Le client crée un GUID et l'envoie dans le cadre de l'entrée)

  2. Ensuite, le client effectue une injection de script normale (JSONP) en tant que paramètre que vous utilisez le même GUID que vous avez utilisé dans la publication FORM. Le service traite les entrées de la session et renvoie les données dans le mode JSONP normal, après quoi la session est détruite.

Bien entendu, cela dépend du fait que vous écrivez le serveur backend.

20
Per

Je sais que c'est une grave nécromancie, mais je pensais publier mon implémentation de JSONP POST en utilisant jQuery, que j'utilise avec succès pour mon widget JS (utilisé pour l'enregistrement et la connexion du client). ):

Fondamentalement, j'utilise une approche IFrame, comme suggéré dans la réponse acceptée. Ce que je fais différemment, c'est après l'envoi de la demande, je surveille si le formulaire peut être atteint dans l'iframe à l'aide d'un minuteur. Lorsque le formulaire ne peut pas être atteint, cela signifie que la demande a été renvoyée. Ensuite, j'utilise une requête JSONP normale pour demander le statut de l'opération.

J'espère que quelqu'un le trouvera utile. Testé dans> = IE8, Chrome, FireFox et Safari.

function JSONPPostForm(form, postUrl, queryStatusUrl, queryStatusSuccessFunc, queryStatusData)
{
    var tmpDiv = $('<div style="display: none;"></div>');
    form.parent().append(tmpDiv);
    var clonedForm = cloneForm(form);
    var iframe = createIFrameWithContent(tmpDiv, clonedForm);

    if (postUrl)
        clonedForm.attr('action', postUrl);

    var postToken = 'JSONPPOST_' + (new Date).getTime();
    clonedForm.attr('id', postToken);
    clonedForm.append('<input name="JSONPPOSTToken" value="'+postToken+'">');
    clonedForm.attr('id', postToken );
    clonedForm.submit();

    var timerId;
    var watchIFrameRedirectHelper = function()
    {
        if (watchIFrameRedirect(iframe, postToken ))
        {
            clearInterval(timerId);
            tmpDiv.remove();
            $.ajax({
                url:  queryStatusUrl,
                data: queryStatusData,
                dataType: "jsonp",
                type: "GET",
                success: queryStatusSuccessFunc
            });
        }
    }

    if (queryStatusUrl && queryStatusSuccessFunc)
        timerId = setInterval(watchIFrameRedirectHelper, 200);
}

function createIFrameWithContent(parent, content)
{
    var iframe = $('<iframe></iframe>');
    parent.append(iframe);

    if (!iframe.contents().find('body').length)
    {
        //For certain IE versions that do not create document content...
        var doc = iframe.contents().get()[0];
        doc.open();
        doc.close();
    }

    iframe.contents().find('body').append(content);
    return iframe;
}

function watchIFrameRedirect(iframe, formId)
{
    try
    {
        if (iframe.contents().find('form[id="' + formId + '"]').length)
            return false;
        else
            return true;
    }
    catch (err)
    {
        return true;
    }
    return false;
}

//This one clones only form, without other HTML markup
function cloneForm(form)
{
    var clonedForm = $('<form></form>');
    //Copy form attributes
    $.each(form.get()[0].attributes, function(i, attr)
    {
        clonedForm.attr(attr.name, attr.value);
    });
    form.find('input, select, textarea').each(function()
    {
        clonedForm.append($(this).clone());
    });

    return clonedForm;
}
7
W.B.

En général, JSONP est implémenté en ajoutant un <script> balise vers le document appelant, telle que l'URL du service JSONP est "src". Le navigateur récupère la source de script avec une transaction HTTP GET.

Désormais, si votre service JSONP se trouve dans le même domaine que votre page d’appel, vous pouvez probablement bricoler quelque chose avec un simple appel $.ajax(). Si ce n'est pas dans le même domaine, alors je ne sais pas comment cela serait possible.

4
Pointy

Vous pouvez utiliser un proxy CORS en utilisant ceci projet . Tout le trafic serait dirigé vers un noeud final de votre domaine et relayerait ces informations vers un domaine externe. Puisque le navigateur enregistre toutes les demandes pour être sur le même domaine, nous sommes en mesure de publier du JSON. REMARQUE: Ceci fonctionne également avec les certificats SSL détenus sur le serveur.

0
Eugene Scray