101 votes

Poster des données vers JsonP

Est-il possible d'envoyer des données à JsonP ? Ou bien toutes les données doivent-elles être transmises dans la chaîne de requête comme une demande GET ?

J'ai beaucoup de données à envoyer au service, en inter-domaine, et elles sont trop volumineuses pour être envoyées via la chaîne de requête.

Quelles sont les options pour contourner ce problème ?

82voto

friedo Points 36209

Il n'est pas possible d'effectuer une opération asynchrone de POST à un service situé sur un autre domaine, en raison de la limitation (tout à fait judicieuse) de l'accès à l'Internet. politique de même origine . JSON-P ne fonctionne que parce que vous êtes autorisé à insérer <script> dans le DOM, et ils peuvent pointer n'importe où.

Vous pouvez, bien sûr, faire d'une page d'un autre domaine l'action d'un formulaire POST normal.

Editar : Il y a des des astuces intéressantes si vous êtes prêt à faire beaucoup d'efforts pour insérer des informations cachées. <iframe> et de s'immiscer dans leurs propriétés.

20voto

Per Points 161

Si vous avez besoin d'envoyer un grand nombre de données à travers le domaine. Je crée généralement un service que vous pouvez appeler en deux étapes :

  1. D'abord le client fait un FORM submit (post allowed cross domain). Le service stocke l'entrée dans la session sur le serveur (en utilisant le GUID comme clé). (le client crée un GUID et l'envoie comme partie de l'entrée).

  2. Puis le client fait un script-inject normal (JSONP) comme paramètre vous utilisez le même GUID que vous avez utilisé dans le post FORM. Le service traite l'entrée de la session et retourne les données à la manière JSONP normale. Après cela, la session est détruite.

Cela dépend bien sûr de la façon dont vous écrivez le serveur dorsal.

7voto

W.B. Points 3131

Je sais que c'est de la nécromancie, mais j'ai pensé poster mon implémentation de JSONP POST en utilisant jQuery, que j'utilise avec succès pour mon widget JS (il est utilisé pour l'enregistrement et la connexion des clients) :

En fait, j'utilise une approche IFrame, comme suggéré dans la réponse acceptée. Ce que je fais différemment, c'est qu'après avoir envoyé la requête, je regarde si le formulaire peut être atteint dans l'iframe, en utilisant une minuterie. Lorsque le formulaire ne peut être atteint, cela signifie que la requête 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;
}

4voto

Pointy Points 172438

Eh bien, en général, JSONP est mis en œuvre par l'ajout d'un <script> au document appelant, de sorte que l'URL du service JSONP soit le "src". Le navigateur récupère la source script avec une transaction HTTP GET.

Maintenant, si votre service JSONP est dans le même domaine que votre page d'appel, alors vous pourriez probablement bricoler quelque chose avec un simple $.ajax() appel. Si ce n'est pas dans le même domaine, alors je ne vois pas comment ce serait possible.

-1voto

BigDong Points 46

Il existe une solution (pirate), je l'ai fait plusieurs fois, vous serez en mesure de poster avec JsonP. (Vous serez en mesure de poster un formulaire, plus grand que 2000 char que vous pouvez utiliser par GET)

Application client Javascript

$.ajax({
  type: "POST", // you request will be a post request
  data: postData, // javascript object with all my params
  url: COMAPIURL, // my backoffice comunication api url
  dataType: "jsonp", // datatype can be json or jsonp
  success: function(result){
    console.dir(result);
  }
});

JAVA :

response.addHeader( "Access-Control-Allow-Origin", "*" ); // open your api to any client 
response.addHeader( "Access-Control-Allow-Methods", "POST" ); // a allow post
response.addHeader( "Access-Control-Max-Age", "1000" ); // time from request to response before timeout

PHP :

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');

En procédant de la sorte, vous ouvrez votre serveur à toutes les requêtes postales, vous devriez le sécuriser à nouveau en fournissant un identifiant ou autre chose.

Avec cette méthode, vous pouvez également changer le type de requête de jsonp à json, les deux fonctionnent, il suffit de définir le bon type de contenu de la réponse.

jsonp

response.setContentType( "text/javascript; charset=utf-8" );

json

response.setContentType( "application/json; charset=utf-8" );

Veuillez noter que votre serveur ne respectera plus la SOP (same origin policy), mais qui s'en soucie ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X