[javascript] JsonP에 데이터 게시

JsonP에 데이터를 게시 할 수 있습니까? 아니면 모든 데이터가 GET 요청으로 쿼리 문자열에 전달되어야합니까?

서비스, ​​도메인 간 전송해야하는 데이터가 많고 쿼리 문자열을 통해 전송하기에는 너무 큽니다.

이 문제를 해결하기위한 옵션은 무엇입니까?



답변

동일한 출처 정책POST 의 (상당히 합리적인) 제한으로 인해 다른 도메인의 서비스에 대해 비동기를 수행하는 것은 불가능합니다 . JSON-P 는 DOM에 태그 를 삽입 할 수 있고 어디든 가리킬 수 있기 때문에 작동합니다 .<script>

물론 다른 도메인의 페이지를 일반 형식 POST의 작업으로 만들 수 있습니다.

편집 : 숨겨진 s를 삽입 하고 속성을 비웃는 데 많은 노력을 기울이고 싶다면 흥미로운 해킹<iframe>있습니다.


답변

많은 데이터를 도메인 간 전송해야하는 경우. 일반적으로 두 단계로 호출 할 수있는 서비스를 만듭니다.

  1. 먼저 클라이언트는 FORM 제출 (포스트 허용 교차 도메인)을 수행합니다. 서비스는 서버의 세션에 입력을 저장합니다 (GUID를 키로 사용). (클라이언트는 GUID를 생성하고 입력의 일부로 보냅니다)

  2. 그런 다음 클라이언트는 FORM 게시물에서 사용한 것과 동일한 GUID를 사용하는 매개 변수로 일반 스크립트 삽입 (JSONP)을 수행합니다. 서비스는 세션의 입력을 처리하고 일반 JSONP 방식으로 데이터를 반환합니다. 이 후 세션이 파괴됩니다.

물론 이것은 서버 백엔드를 작성하는 것에 달려 있습니다.


답변

나는 이것이 심각한 강령술이라는 것을 알고 있지만 jQuery를 사용하여 JSONP POST 구현을 게시 할 것이라고 생각했는데, 이는 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;
}


답변

일반적으로 JSONP는 <script>JSONP 서비스의 URL이 “src”가되도록 호출 문서에 태그를 추가하여 구현됩니다 . 브라우저는 HTTP GET 트랜잭션으로 스크립트 소스를 가져옵니다.

이제 JSONP 서비스가 호출 페이지와 동일한 도메인에있는 경우 간단한 $.ajax()호출로 무언가를 결합 할 수 있습니다. 같은 도메인에 있지 않다면 어떻게 가능한지 잘 모르겠습니다.


답변

프로젝트 를 사용하여 CORS 프록시 를 사용할 수 있습니다 . 모든 트래픽을 도메인의 엔드 포인트로 전달하고 해당 정보를 외부 도메인으로 릴레이합니다. 브라우저가 모든 요청을 동일한 도메인에 등록하기 때문에 JSON을 게시 할 수 있습니다.
참고 : 이는 서버에있는 SSL 인증서에서도 작동합니다.


답변

여러 번 해본 (해킹) 솔루션이 있습니다. JsonP로 게시 할 수 있습니다. (GET에서 사용할 수있는 것보다 2000 자 이상인 양식을 게시 할 수 있습니다.)

클라이언트 애플리케이션 자바 스크립트

$.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);
  }
});

자바:

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');

이렇게하면 모든 게시 요청에 대해 서버를 열고 ident 또는 다른 것을 제공하여이를 다시 보호해야합니다.

이 방법을 사용하면 요청 유형을 jsonp에서 json으로 변경할 수도 있습니다. 둘 다 작동하고 올바른 응답 콘텐츠 유형을 설정하기 만하면됩니다.

jsonp

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

json

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

서버가 더 이상 SOP (동일한 원산지 정책)를 존중하지 않지만 누가 신경 쓰나요?


답변

가능합니다. 여기 내 해결책이 있습니다.

자바 스크립트에서 :

jQuery.post("url.php",data).complete(function(data) {
    eval(data.responseText.trim());
});
function handleRequest(data){
    ....
}

url.php에서 :

echo "handleRequest(".$responseData.")";