สามารถโพสต์ข้อมูลไปยัง JsonP ได้หรือไม่? หรือข้อมูลทั้งหมดจะต้องถูกส่งผ่านในสตริงการสืบค้นเป็นคำขอ GET?
ฉันมีข้อมูลจำนวนมากที่ต้องส่งไปยังบริการข้ามโดเมนและมีขนาดใหญ่เกินไปที่จะส่งผ่านสตริงการสืบค้น
อะไรคือตัวเลือกสำหรับการหลีกเลี่ยงสิ่งนี้?
สามารถโพสต์ข้อมูลไปยัง JsonP ได้หรือไม่? หรือข้อมูลทั้งหมดจะต้องถูกส่งผ่านในสตริงการสืบค้นเป็นคำขอ GET?
ฉันมีข้อมูลจำนวนมากที่ต้องส่งไปยังบริการข้ามโดเมนและมีขนาดใหญ่เกินไปที่จะส่งผ่านสตริงการสืบค้น
อะไรคือตัวเลือกสำหรับการหลีกเลี่ยงสิ่งนี้?
คำตอบ:
มันเป็นไปไม่ได้ที่จะทำไม่ตรงกันPOST
ที่จะให้บริการในโดเมนอื่นเนื่องจากการ (ที่เหมาะสมมาก) ข้อ จำกัด ของนโยบายกำเนิดเดียวกัน JSON-P ใช้งานได้ก็ต่อเมื่อคุณได้รับอนุญาตให้แทรก<script>
แท็กลงใน DOM และสามารถชี้ไปที่ใดก็ได้
แน่นอนคุณสามารถสร้างเพจบนโดเมนอื่นโดยใช้รูปแบบปกติ POST
แก้ไข : มีแฮ็กที่น่าสนใจบางอย่างอยู่ที่นั่นหากคุณเต็มใจที่จะใช้ความพยายามอย่างมากในการแทรก<iframe>
s ที่ซ่อนอยู่และทำให้ยุ่งเกี่ยวกับคุณสมบัติของพวกเขา
POST
คำขอไปยังโดเมนอื่น ๆ CORS
ตราบใดที่ทั้งสองว่าโดเมนและการสนับสนุนเบราว์เซอร์ของคุณ แต่มันเป็นความจริงทั้งหมดว่าPOST
และJSONP
จะไม่เข้ากัน
<script>
แท็กที่ชี้ไปยังโดเมนอื่น วิธีเดียวในการดำเนินการคำขอ POST ในเบราว์เซอร์คือผ่านรูปแบบ HTML หรือ XMLHttpRequest
หากคุณต้องการส่งข้อมูลจำนวนมากข้ามโดเมน โดยปกติฉันจะสร้างบริการที่คุณสามารถโทรได้ในสองขั้นตอน:
ขั้นแรกให้ลูกค้าทำการส่งแบบฟอร์ม (อนุญาตให้โพสต์ข้ามโดเมน) บริการจัดเก็บอินพุตในเซสชันบนเซิร์ฟเวอร์ (โดยใช้ GUID เป็นคีย์) (ไคลเอนต์สร้าง GUID และส่งเป็นส่วนหนึ่งของอินพุต)
จากนั้นไคลเอ็นต์จะทำการฉีดสคริปต์ (JSONP) ตามปกติเป็นพารามิเตอร์ที่คุณใช้ GUID เดียวกับที่คุณใช้ในโพสต์แบบฟอร์ม บริการประมวลผลอินพุตจากเซสชันและส่งคืนข้อมูลในรูปแบบ JSONP ปกติ หลังจากนี้เซสชันจะถูกทำลาย
แน่นอนว่านี่ขึ้นอยู่กับว่าคุณเขียนเซิร์ฟเวอร์แบ็กเอนด์
XMLHttpRequest
ไม่ควรมีส่วนร่วมเลย คำตอบของ Per ใช้การส่งแบบฟอร์มปกติเพื่อสร้างคำขอ POST จากนั้นจึงฉีดองค์ประกอบสคริปต์เพื่อสร้างคำขอ GET
ฉันรู้ว่านี่เป็นความผิดปกติที่ร้ายแรง แต่ฉันคิดว่าฉันจะโพสต์การใช้งาน 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;
}
โดยทั่วไป JSONP จะถูกนำไปใช้โดยการเพิ่ม<script>
แท็กลงในเอกสารการโทรดังนั้น URL ของบริการ JSONP คือ "src" เบราว์เซอร์ดึงซอร์สของสคริปต์ด้วยธุรกรรม HTTP GET
ตอนนี้หากบริการ JSONP ของคุณอยู่ในโดเมนเดียวกับหน้าการโทรของคุณคุณอาจจะสามารถใช้งานร่วมกันได้ด้วยการ$.ajax()
โทรธรรมดา หากไม่ได้อยู่ในโดเมนเดียวกันฉันก็ไม่แน่ใจว่าจะเป็นไปได้อย่างไร
CORS
ก็จะเป็นไปได้ตราบเท่าที่เบราว์เซอร์ยังรองรับ ในกรณีนี้คุณจะใช้ธรรมดามากกว่าJSON
JSONP
คุณสามารถใช้CORS Proxyโดยใช้โปรเจ็กต์นี้ ซึ่งจะนำการรับส่งข้อมูลทั้งหมดไปยังปลายทางบนโดเมนของคุณและส่งต่อข้อมูลนั้นไปยังโดเมนภายนอก เนื่องจากเบราว์เซอร์กำลังลงทะเบียนคำขอทั้งหมดให้อยู่ในโดเมนเดียวกันเราจึงสามารถโพสต์ JSON ได้ หมายเหตุ: ใช้งานได้กับใบรับรอง SSL ที่อยู่บนเซิร์ฟเวอร์
มีวิธี (แฮ็ก) ที่ฉันเคยทำหลายครั้งคุณจะสามารถโพสต์ด้วย JsonP (คุณจะสามารถโพสต์แบบฟอร์มที่มีขนาดใหญ่กว่า 2,000 ตัวอักษรกว่าที่ GET ใช้ได้)
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');
เมื่อทำเช่นนี้คุณกำลังเปิดเซิร์ฟเวอร์ของคุณเพื่อขอโพสต์ใด ๆ คุณควรรักษาความปลอดภัยอีกครั้งโดยการระบุรหัสหรืออย่างอื่น
ด้วยวิธีนี้คุณยังสามารถเปลี่ยนประเภทคำขอจาก jsonp เป็น json ได้ทั้งสองอย่างเพียงตั้งค่าประเภทเนื้อหาตอบกลับที่ถูกต้อง
jsonp
response.setContentType( "text/javascript; charset=utf-8" );
json
response.setContentType( "application/json; charset=utf-8" );
โปรดอย่าว่าเซิร์ฟเวอร์ของคุณจะไม่เคารพ SOP อีกต่อไป (นโยบายต้นทางเดียวกัน) แต่ใครจะสนล่ะ?
<script>
แท็กลงใน HTML DOM ของคุณ (ห่าคุณยังสามารถใช้ในแอปเดสก์ท็อปได้ด้วยกล่าวว่าคุณต้องการส่งคำขอ JSON หลายรายการไปยังเซิร์ฟเวอร์เดียวกันและต้องการใช้ชื่อฟังก์ชัน เป็นรหัสติดตามคำขอเป็นต้น)
เป็นไปได้นี่คือทางออกของฉัน:
ในจาวาสคริปต์ของคุณ:
jQuery.post("url.php",data).complete(function(data) {
eval(data.responseText.trim());
});
function handleRequest(data){
....
}
ใน url.php ของคุณ:
echo "handleRequest(".$responseData.")";