JsonP에 데이터를 게시 할 수 있습니까? 아니면 모든 데이터가 GET 요청으로 쿼리 문자열에 전달되어야합니까?
서비스, 도메인 간 전송해야하는 데이터가 많고 쿼리 문자열을 통해 전송하기에는 너무 큽니다.
이 문제를 해결하기위한 옵션은 무엇입니까?
답변
동일한 출처 정책POST
의 (상당히 합리적인) 제한으로 인해 다른 도메인의 서비스에 대해 비동기를 수행하는 것은 불가능합니다 . JSON-P 는 DOM에 태그 를 삽입 할 수 있고 어디든 가리킬 수 있기 때문에 작동합니다 .<script>
물론 다른 도메인의 페이지를 일반 형식 POST의 작업으로 만들 수 있습니다.
편집 : 숨겨진 s를 삽입 하고 속성을 비웃는 데 많은 노력을 기울이고 싶다면 흥미로운 해킹 이 <iframe>
있습니다.
답변
많은 데이터를 도메인 간 전송해야하는 경우. 일반적으로 두 단계로 호출 할 수있는 서비스를 만듭니다.
-
먼저 클라이언트는 FORM 제출 (포스트 허용 교차 도메인)을 수행합니다. 서비스는 서버의 세션에 입력을 저장합니다 (GUID를 키로 사용). (클라이언트는 GUID를 생성하고 입력의 일부로 보냅니다)
-
그런 다음 클라이언트는 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.")";