답변:
동일한 출처 정책POST
의 (상당히 합리적인) 제한으로 인해 다른 도메인의 서비스에 대해 비동기를 수행하는 것은 불가능합니다 . JSON-P 는 DOM에 태그 를 삽입 할 수 있고 어디든 가리킬 수 있기 때문에 작동합니다 .<script>
물론 다른 도메인의 페이지를 일반 형식 POST의 작업으로 만들 수 있습니다.
편집 : 숨겨진 s를 삽입 하고 속성을 비웃는 데 많은 노력을 기울이고 싶다면 흥미로운 해킹 이 <iframe>
있습니다.
POST
해당 도메인과 브라우저가 모두 지원하는 한 다른 도메인에 대한 요청을 확실히 수행 할 수 있습니다 CORS
. 그러나 그것은 완전히 사실 POST
이며 JSONP
양립 할 수 없습니다.
<script>
다른 도메인을 가리키는 태그를 삽입하여 구현됩니다 . 브라우저에서 POST 요청을 실행하는 유일한 방법은 HTML 양식 또는 XMLHttpRequest를 사용하는 것입니다.
많은 데이터를 도메인 간 전송해야하는 경우. 일반적으로 두 단계로 호출 할 수있는 서비스를 만듭니다.
먼저 클라이언트는 FORM 제출 (포스트 허용 교차 도메인)을 수행합니다. 서비스는 서버의 세션에 입력을 저장합니다 (GUID를 키로 사용). (클라이언트는 GUID를 생성하고 입력의 일부로 보냅니다)
그런 다음 클라이언트는 FORM 게시물에서 사용한 것과 동일한 GUID를 사용하는 매개 변수로 일반 스크립트 삽입 (JSONP)을 수행합니다. 서비스는 세션의 입력을 처리하고 일반 JSONP 방식으로 데이터를 반환합니다. 이 후 세션이 파괴됩니다.
물론 이것은 서버 백엔드를 작성하는 것에 달려 있습니다.
XMLHttpRequest
전혀 관여해서는 안됩니다. Per의 답변은 일반 양식 제출을 사용하여 POST 요청을 한 다음 스크립트 요소 삽입을 사용하여 GET 요청을 만듭니다.
나는 이것이 심각한 강령술이라는 것을 알고 있지만 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
하는 대신 JSONP
.
여러 번 해본 (해킹) 솔루션이 있습니다. 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 (동일한 원산지 정책)를 존중하지 않지만 누가 신경 쓰나요?
<script>
HTML DOM에 태그를 삽입하는 것 외에 JSON 및 JSONP 데이터 표기법을 모두 사용할 수 있습니다 (데스크톱 앱에서도 사용할 수 있습니다. 동일한 서버에 여러 JSON 요청을하고 함수 이름을 사용하고 싶다고 가정 해 보겠습니다.) 예를 들어 요청 추적 ID).
가능합니다. 여기 내 해결책이 있습니다.
자바 스크립트에서 :
jQuery.post("url.php",data).complete(function(data) {
eval(data.responseText.trim());
});
function handleRequest(data){
....
}
url.php에서 :
echo "handleRequest(".$responseData.")";