web-dev-qa-db-ja.com

JsonPへのデータの投稿

JsonPにデータを投稿することは可能ですか?または、すべてのデータをGETリクエストとしてクエリ文字列で渡す必要がありますか?

クロスドメインのサービスに送信する必要がある多くのデータがあり、クエリ文字列を介して送信するには大きすぎます

これを回避するためのオプションは何ですか?

101
ChrisCa

同じオリジンポリシー の(かなり賢明な)制限のため、別のドメインのサービスに対して非同期POSTを実行することはできません。 JSON-Pが機能するのは、<script>はDOMにタグ付けされ、どこでも指すことができます。

もちろん、別のドメインのページを通常のフォームPOSTのアクションにすることができます。

Edit興味深いハック 隠れた<iframe>sとそのプロパティをいじくり回します。

82
friedo

クロスドメインで大量のデータを送信する必要がある場合。通常、2つのステップで呼び出すことができるサービスを作成します。

  1. 最初に、クライアントはFORMを送信します(クロスドメインを許可された投稿)。サービスは、サーバー上のセッションに入力を保存します(GUIDをキーとして使用)。(クライアントはGUIDを作成し、その一部として送信します入力)

  2. 次に、クライアントは、FORMポストで使用したのと同じGUIDを使用するパラメーターとして、通常のスクリプト挿入(JSONP)を実行します。サービスは、セッションからの入力を処理し、通常のJSONP-fashionこの後、セッションは破棄されます。

もちろん、これはサーバーバックエンドを作成することに依存しています。

20
Per

これは深刻なネクロマンシーであることはわかっていますが、JSONPの実装を投稿すると思いましたPOST jQueryを使用して、これをJSウィジェットに正常に使用しています(これは顧客の登録とログイン):

基本的に、受け入れられた回答で提案されているように、私はIFrameアプローチを使用しています。私が異なってやっているのは、リクエストを送信した後、タイマーを使用してiframeでフォームに到達できるかどうかを監視しています。フォームに到達できない場合、リクエストが返されたことを意味します。次に、通常のJSONPリクエストを使用して、操作のステータスを照会しています。

誰かがそれを役に立つと思うことを願っています。 > = IE8、Chrome、FireFox、および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.

JSONPサービスのURLが「src」となるように、JSONPは_<script>_タグを呼び出し側ドキュメントに追加することで実装されます。ブラウザは、HTTP GETトランザクションでスクリプトソースを取得します。

これで、JSONPサービスが呼び出しページと同じドメインにある場合、おそらく単純な$.ajax()呼び出しで何かをまとめることができます。同じドメインにない場合、どのように可能になるかわかりません。

4
Pointy

この project を使用して CORS Proxy を使用できます。すべてのトラフィックをドメインのエンドポイントに転送し、その情報を外部ドメインに中継します。ブラウザはすべてのリクエストを同じドメインに登録するので、JSONを投稿できます。 注:これは、サーバーに保持されているSSL証明書でも機能します。

0
Eugene Scray