ฉันจะส่งคำขอ POST ข้ามโดเมนผ่าน JavaScript ได้อย่างไร


568

ฉันจะส่งคำขอ POST ข้ามโดเมนผ่าน JavaScript ได้อย่างไร

หมายเหตุ - ไม่ควรรีเฟรชหน้าเว็บและฉันจำเป็นต้องคว้าและแยกการตอบสนองในภายหลัง


ฉันต้องการทราบเล็กน้อยเกี่ยวกับกรณีการใช้งานที่ให้คุณลองทำสิ่งนี้ คุณช่วยเล่าเรื่องเกี่ยวกับมันหน่อยได้ไหม
mkoeller

โดยทั่วไปฉันกำลังทำงานกับสคริปต์ที่ต้องการส่งข้อความบางส่วนจากไฟล์ HTML ไปยังเซิร์ฟเวอร์อื่นเพื่อการประมวลผล
Ido Schacham

3
คุณสามารถตั้งค่าพร็อกซีที่ทำสิ่งนี้บนฝั่งเซิร์ฟเวอร์และให้ผลลัพธ์สคริปต์ของคุณหรือไม่ หรือมันจะต้องเป็นจาวาสคริปต์ 100%?
Sasha Chedygov

คำตอบ:


382

อัปเดต:ก่อนที่จะดำเนินการต่อทุกคนควรอ่านและทำความเข้าใจกับการสอน html5rocksบน CORS ง่ายต่อการเข้าใจและชัดเจนมาก

หากคุณควบคุมเซิร์ฟเวอร์ที่ถูก POSTed เพียงแค่ใช้ประโยชน์จาก "มาตรฐานการแบ่งปันทรัพยากรข้ามแหล่งกำเนิด" โดยการตั้งค่าส่วนหัวการตอบสนองบนเซิร์ฟเวอร์ คำตอบนี้จะกล่าวถึงในคำตอบอื่น ๆ ในหัวข้อนี้ แต่ไม่ชัดเจนในความคิดของฉัน

ในระยะสั้นนี่คือวิธีการที่คุณทำ POST ข้ามโดเมนจาก from.com/1.html ไปที่ to.com/postHere.php (โดยใช้ตัวอย่าง PHP) หมายเหตุ: คุณจะต้องตั้งค่าAccess-Control-Allow-OriginสำหรับOPTIONSคำขอNON เท่านั้น- ตัวอย่างนี้ตั้งค่าส่วนหัวทั้งหมดสำหรับข้อมูลโค้ดที่เล็กกว่าเสมอ

  1. ใน postHere.php ตั้งค่าต่อไปนี้:

    switch ($_SERVER['HTTP_ORIGIN']) {
        case 'http://from.com': case 'https://from.com':
        header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
        header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
        break;
    }

    สิ่งนี้ทำให้สคริปต์ของคุณสร้าง POST, GET และ OPTIONS ข้ามโดเมนได้ สิ่งนี้จะชัดเจนเมื่อคุณอ่านต่อ ...

  2. ตั้งค่า POST ข้ามโดเมนของคุณจาก JS (ตัวอย่าง jQuery):

    $.ajax({
        type: 'POST',
        url: 'https://to.com/postHere.php',
        crossDomain: true,
        data: '{"some":"json"}',
        dataType: 'json',
        success: function(responseData, textStatus, jqXHR) {
            var value = responseData.someKey;
        },
        error: function (responseData, textStatus, errorThrown) {
            alert('POST failed.');
        }
    });

เมื่อคุณทำ POST ในขั้นตอนที่ 2 เบราว์เซอร์ของคุณจะส่งวิธี "OPTIONS" ไปยังเซิร์ฟเวอร์ นี่คือ "สูดอากาศ" โดยเบราว์เซอร์เพื่อดูว่าเซิร์ฟเวอร์นั้นยอดเยี่ยมกับคุณหรือไม่ เซิร์ฟเวอร์ตอบกลับด้วย "Access-Control-Allow-Origin" เพื่อบอกเบราว์เซอร์ว่าตกลงเพื่อ POST | GET | ORIGIN ถ้าคำขอมาจาก " http://from.com " หรือ " https://from.com " เนื่องจากเซิร์ฟเวอร์ตกลงกับเบราว์เซอร์จะทำการร้องขอที่สอง (ครั้งนี้เป็น POST) เป็นการดีที่จะให้ลูกค้าของคุณตั้งค่าประเภทเนื้อหาที่กำลังส่ง - ดังนั้นคุณจะต้องอนุญาตด้วยเช่นกัน

MDN มีการเขียนที่ยอดเยี่ยมเกี่ยวกับการควบคุมการเข้าถึง HTTPซึ่งมีรายละเอียดเกี่ยวกับการทำงานของโฟลว์ทั้งหมด ตามเอกสารของพวกเขามันควร "ทำงานในเบราว์เซอร์ที่สนับสนุน XMLHttpRequest ข้ามไซต์" นี่เป็นสิ่งที่ทำให้เข้าใจผิดเล็กน้อยเนื่องจากฉันคิดว่ามีเพียงเบราว์เซอร์ที่ทันสมัยเท่านั้นที่อนุญาตการข้าม POST ฉันตรวจสอบแล้วว่าใช้ได้กับซาฟารีโครเมี่ยม FF 3.6 เท่านั้น

โปรดจำไว้ว่าหากคุณทำสิ่งนี้:

  1. เซิร์ฟเวอร์ของคุณจะต้องจัดการ 2 คำขอต่อการดำเนินการ
  2. คุณจะต้องคิดถึงผลกระทบด้านความปลอดภัย ระวังก่อนทำบางอย่างเช่น 'Access-Control-Allow-Origin: *'
  3. สิ่งนี้จะไม่ทำงานบนเบราว์เซอร์มือถือ จากประสบการณ์ของฉันพวกเขาไม่อนุญาตให้ข้าม POST เลย ฉันทดสอบ Android, iPad, iPhone แล้ว
  4. มีข้อผิดพลาดที่ค่อนข้างใหญ่ใน FF <3.6 ซึ่งหากเซิร์ฟเวอร์ส่งคืนรหัสการตอบสนองที่ไม่ใช่ 400 และมีเนื้อหาของการตอบกลับ (เช่นข้อผิดพลาดในการตรวจสอบความถูกต้อง) FF 3.6 จะไม่ได้รับเนื้อหาการตอบกลับ นี่เป็นความเจ็บปวดครั้งใหญ่ในตูดเนื่องจากคุณไม่สามารถใช้วิธีปฏิบัติที่ดีได้ ดูข้อผิดพลาดที่นี่ (มันยื่นใต้ jQuery แต่ฉันเดาว่ามันเป็นข้อผิดพลาด FF - ดูเหมือนว่าจะได้รับการแก้ไขใน FF4)
  5. ส่งคืนส่วนหัวด้านบนเสมอไม่ใช่เฉพาะกับคำขอ OPTION FF ต้องการมันในการตอบสนองจาก POST

มันสามารถส่งคืน html ได้หรือไม่ ฉันต้องการส่งคืน html และบางอย่างไม่ทำงาน ...
denis_n

ใช่คุณควรจะสามารถ ไม่เคยลองมาก่อน เซิร์ฟเวอร์ของคุณส่งคืน 200 หรือไม่ เซิร์ฟเวอร์ของคุณส่งคืนส่วนหัวในคำขอ OPTIONs และ POST หรือไม่ ฉันได้อัปเดตคำตอบพร้อมรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้แล้ว ตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณตอบสนองด้วยส่วนหัวประเภทเนื้อหาที่ถูกต้องเช่นกัน (เช่นข้อความ / html) การแนะนำของฉันคือการใช้ google chrome หน้าคลิกขวา> ตรวจสอบองค์ประกอบ คลิกที่แท็บเครือข่ายและดู POST และการตอบสนอง ควรให้ข้อมูลคุณเกี่ยวกับสิ่งที่ผิดพลาด
rynop

ฉันได้พยายามนี้ แต่ยังคงได้รับ400 Bad RequestในOPTIONSการร้องขอ และในfirefoxคำขอที่สองของPOSTไม่เคยทำ :(
Zain Shaikh

มีวิธีการเรียกเครื่องท้องถิ่นของคุณในคำสั่งกรณีของคุณด้านบนหรือไม่ หรือคุณเพียงแค่ใช้ * ในกรณีนี้เพื่ออนุญาตต้นกำเนิด
ทอดด์แวนซ์

1
สิ่งนี้ได้รับการแก้ไขครั้งล่าสุดเมื่อ 4 ปีก่อน - งานนี้จะใช้กับเบราว์เซอร์มือถือหรือไม่
frankpinto

121

หากคุณสามารถควบคุมเซิร์ฟเวอร์ระยะไกลคุณอาจจะใช้ล ธ ที่อธิบายไว้ในคำตอบนี้ ; มันรองรับ IE8 ขึ้นไปและ FF, GC และ Safari รุ่นล่าสุดทั้งหมด (แต่ใน IE8 และ 9 CORS จะไม่อนุญาตให้คุณส่งคุกกี้ตามคำขอ)

ดังนั้นถ้าคุณ ไม่ได้ควบคุมเซิร์ฟเวอร์ระยะไกลหรือหากคุณต้องรองรับ IE7 หรือหากคุณต้องการคุกกี้และคุณต้องรองรับ IE8 / 9 คุณอาจต้องใช้เทคนิค iframe

  1. สร้าง iframe ด้วยชื่อเฉพาะ (iframes ใช้เนมสเปซส่วนกลางสำหรับเบราว์เซอร์ทั้งหมดดังนั้นเลือกชื่อที่จะไม่มีเว็บไซต์อื่นใช้)
  2. สร้างฟอร์มที่มีอินพุตที่ซ่อนอยู่โดยกำหนดเป้าหมายไปที่ iframe
  3. ส่งแบบฟอร์ม

นี่คือตัวอย่างรหัส ฉันทดสอบกับ IE6, IE7, IE8, IE9, FF4, GC11, S5

function crossDomainPost() {
  // Add the iframe with a unique name
  var iframe = document.createElement("iframe");
  var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
  document.body.appendChild(iframe);
  iframe.style.display = "none";
  iframe.contentWindow.name = uniqueString;

  // construct a form with hidden inputs, targeting the iframe
  var form = document.createElement("form");
  form.target = uniqueString;
  form.action = "http://INSERT_YOUR_URL_HERE";
  form.method = "POST";

  // repeat for each parameter
  var input = document.createElement("input");
  input.type = "hidden";
  input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
  input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
  form.appendChild(input);

  document.body.appendChild(form);
  form.submit();
}

ระวัง! คุณจะไม่สามารถอ่านการตอบสนองของ POST โดยตรงเนื่องจาก iframe มีอยู่ในโดเมนแยกต่างหาก เฟรมไม่ได้รับอนุญาตให้สื่อสารซึ่งกันและกันจากโดเมนที่ต่างกัน นี่คือนโยบายที่มาเดียวกัน

หากคุณควบคุมเซิร์ฟเวอร์ระยะไกล แต่คุณไม่สามารถใช้ CORS (เช่นเนื่องจากคุณใช้ IE8 / IE9 และคุณจำเป็นต้องใช้คุกกี้) มีวิธีการแก้ไขนโยบายแหล่งกำเนิดเดียวกันเช่นโดยใช้window.postMessageและ / หรือ หนึ่งในจำนวนไลบรารีที่อนุญาตให้คุณส่งข้อความข้ามเฟรมในเบราว์เซอร์รุ่นเก่า:

หากคุณไม่ได้ควบคุมเซิร์ฟเวอร์ระยะไกลคุณจะไม่สามารถอ่านการตอบสนองของ POST, ช่วงเวลาได้ มันจะทำให้เกิดปัญหาด้านความปลอดภัยเป็นอย่างอื่น


2
คุณจะต้องตั้งค่า form.target เป็นอย่างอื่นเบราว์เซอร์จะนำทางจากไซต์ของคุณไปยัง URL การกระทำของฟอร์ม นอกจากนี้สตริงต้องไม่ซ้ำกัน หากมีเฟรมหรือหน้าต่างอื่น ๆ ที่ใช้ชื่อเดียวกันแบบฟอร์มสามารถโพสต์ไปที่หน้าต่างนั้นแทน iframe ของคุณ แต่มันต้องมีความพิเศษขนาดไหน? อาจจะไม่มาก โอกาสที่การอุดตันจะค่อนข้างเล็ก ยัก
แดน Fabulich

1
@Nawaz ดังที่ฉันได้กล่าวไว้ในคำตอบของฉันคุณจะต้องทำการสื่อสารข้ามเฟรมเพื่อให้ได้ผลลัพธ์ในหน้าเว็บของคุณ ต้องการให้คุณควบคุมเว็บเซิร์ฟเวอร์ระยะไกลเพื่อให้คุณสามารถแก้ไขการตอบสนองเพื่อให้สามารถสื่อสารกับเว็บเพจของคุณได้ (สำหรับสิ่งหนึ่งเซิร์ฟเวอร์จะต้องตอบกลับด้วย HTML หากเซิร์ฟเวอร์ตอบกลับด้วย XML ดิบจะไม่สามารถทำการสื่อสารข้ามเฟรมได้)
Dan Fabulich

1
+1 - นี่เป็นทางออกที่ดีที่สุดที่ฉันพบถ้าคุณไม่สามารถเข้าถึงเซิร์ฟเวอร์
James Long

1
@VojtechB ไม่นั่นจะเป็นช่องโหว่ความปลอดภัย
Dan Fabulich

1
@Andrus คุณสามารถอ่านผลลัพธ์ของ POST ได้เฉพาะในกรณีที่คุณควบคุมเซิร์ฟเวอร์เท่านั้น! ดูในคำตอบนั้นมันบอกว่า "do X บนผู้ส่ง [ลูกค้า], ทำ Y บนผู้รับ [เซิร์ฟเวอร์]" หากคุณไม่ควบคุมผู้รับ / เซิร์ฟเวอร์คุณจะไม่สามารถทำ Y ได้ดังนั้นคุณจึงไม่สามารถอ่านผลลัพธ์ของ POST ได้
Dan Fabulich

48
  1. สร้าง iFrame
  2. ใส่แบบฟอร์มในนั้นด้วยอินพุตที่ซ่อนอยู่
  3. ตั้งค่าการกระทำของฟอร์มเป็น URL
  4. เพิ่ม iframe ให้กับเอกสาร
  5. ส่งแบบฟอร์ม

pseudocode

 var ifr = document.createElement('iframe');
 var frm = document.createElement('form');
 frm.setAttribute("action", "yoururl");
 frm.setAttribute("method", "post");

 // create hidden inputs, add them
 // not shown, but similar (create, setAttribute, appendChild)

 ifr.appendChild(frm);
 document.body.appendChild(ifr);
 frm.submit();

คุณอาจต้องการสไตล์ iframe เพื่อซ่อนและวางตำแหน่งอย่างแน่นอน ไม่แน่ใจว่าเบราว์เซอร์อนุญาตการโพสต์ข้ามไซต์ แต่ถ้าเป็นเช่นนั้นนี่เป็นวิธีการ


4
ที่จริงแล้วมันไม่ถูกต้องเล็กน้อยเนื่องจาก ifr.appendChild (frm); จะไม่ทำงาน. iframe เป็นการอ้างอิงถึงวัตถุหน้าต่างและไม่มีวิธีการ appendChild สำหรับมัน คุณจะต้องคว้าโหนดเอกสารใน iframe ก่อน สิ่งนี้ต้องการการตรวจจับคุณสมบัติเพื่อทำงานกับเบราว์เซอร์
Rakesh Pai

ขอบคุณ พบลิงก์ที่มีประโยชน์เหล่านี้เกี่ยวกับเรื่องนี้: bindzus.wordpress.com/2007/12/24/… developer.apple.com/internet/webcontent/iframe.html
Ido Schacham

19
ปัญหา! การตอบสนองที่ได้รับใน iframe นั้นอยู่ที่โดเมนอื่นดังนั้นหน้าต่างหลักจึงไม่สามารถเข้าถึงได้และ iframe นั้นไม่สามารถเข้าถึงหน้าต่างหลักได้ ดังนั้นการแก้ปัญหานี้เท่านั้นดูเหมือนว่าดีสำหรับการทำโพสต์ แต่คุณไม่สามารถแยกการตอบสนองหลังจากนั้น :(
สั่นสะท้าน Schacham

2
ลองตั้งค่า onload ในแท็ก body ของการตอบกลับไปยังฟังก์ชัน JavaScript ที่เรียกใช้ฟังก์ชันในพาเรนต์ด้วยสตริงการตอบกลับ
Lou Franco

คำตอบนี้ไม่ได้ผลสำหรับฉัน ฉันโพสต์รูปแบบของฉันเองด้านล่าง
Dan Fabulich

24

ง่าย ๆ เข้าไว้:

  1. POST ข้ามโดเมน:
    ใช้crossDomain: true,

  2. ไม่ควรรีเฟรชหน้าเว็บ:
    ไม่หน้าจะไม่รีเฟรชหน้าเว็บเนื่องจากจะมีการโทรกลับsuccessหรือerrorasync เมื่อเซิร์ฟเวอร์ส่งการตอบกลับ


สคริปต์ตัวอย่าง:

$.ajax({
        type: "POST",
        url: "http://www.yoururl.com/",
        crossDomain: true,
        data: 'param1=value1&param2=value2',
        success: function (data) {
            // do something with server response data
        },
        error: function (err) {
            // handle your error logic here
        }
    });

8
crossDomain: trueแปลกไม่มีอะไรเกี่ยวข้องกับคำขอข้ามโดเมนจริง ๆ หากการร้องขอข้ามโดเมน jquery ตั้งค่านี้เป็นจริงโดยอัตโนมัติ
Kevin B

16

หากคุณสามารถเข้าถึงเซิร์ฟเวอร์ทั้งหมดที่เกี่ยวข้องให้ใส่สิ่งต่อไปนี้ในส่วนหัวของการตอบกลับสำหรับหน้าที่ถูกร้องขอในโดเมนอื่น:

PHP:

header('Access-Control-Allow-Origin: *');

ตัวอย่างเช่นในรหัส xmlrpc.php ของ Drupal คุณจะทำสิ่งนี้:

function xmlrpc_server_output($xml) {
    $xml = '<?xml version="1.0"?>'."\n". $xml;
    header('Connection: close');
    header('Content-Length: '. strlen($xml));
    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/x-www-form-urlencoded');
    header('Date: '. date('r'));
    // $xml = str_replace("\n", " ", $xml); 

    echo $xml;
    exit;
}

นี่อาจสร้างปัญหาด้านความปลอดภัยและคุณควรตรวจสอบให้แน่ใจว่าคุณใช้มาตรการที่เหมาะสมเพื่อตรวจสอบคำขอ



6
  1. สร้าง iframes ที่ซ่อนอยู่สองอัน (เพิ่ม "display: none;" ในสไตล์ css) ทำให้ iframe ที่สองของคุณชี้ไปที่บางอย่างในโดเมนของคุณเอง

  2. สร้างฟอร์มที่ซ่อนไว้ตั้งค่าวิธีการเป็น "โพสต์" โดยมีเป้าหมาย = iframe แรกของคุณและตั้งค่าประเภทเอกสารเป็น "หลายส่วน / แบบฟอร์มข้อมูล" (ฉันคิดว่าคุณต้องการทำ POST เพราะคุณต้องการส่งข้อมูลหลายส่วนเช่นรูปภาพ ?)

  3. เมื่อพร้อมแล้วให้ส่งแบบฟอร์ม () POST

  4. หากคุณได้รับโดเมนอื่นเพื่อส่งคืนจาวาสคริปต์ที่จะทำการสื่อสารข้ามโดเมนด้วย Iframes ( http://softwareas.com/cross-domain-communication-with-iframes ) คุณจะโชคดีและคุณสามารถจับคำตอบได้ เช่นกัน

แน่นอนถ้าคุณต้องการใช้เซิร์ฟเวอร์เป็นพร็อกซีคุณสามารถหลีกเลี่ยงสิ่งเหล่านี้ได้ทั้งหมด เพียงส่งแบบฟอร์มไปยังเซิร์ฟเวอร์ของคุณเองซึ่งจะส่งคำขอไปยังเซิร์ฟเวอร์อื่น (สมมติว่าเซิร์ฟเวอร์อื่นไม่ได้ถูกตั้งค่าให้สังเกตความแตกต่างของ IP) รับการตอบกลับและส่งคืนสิ่งที่คุณต้องการ


6

สิ่งสำคัญอีกข้อหนึ่งที่ควรทราบ !!! ในตัวอย่างข้างต้นก็อธิบายวิธีการใช้งาน

$.ajax({
    type     : 'POST',
    dataType : 'json', 
    url      : 'another-remote-server',
    ...
});

JQuery 1.6 และต่ำกว่ามีข้อบกพร่องที่มี XHR ข้ามโดเมน ตาม Firebug ไม่มีการร้องขอใดนอกจากตัวเลือกถูกส่ง ไม่มีโพสต์ เลย

ใช้เวลาทดสอบ 5 ชั่วโมง / ปรับรหัสของฉัน การเพิ่มส่วนหัวจำนวนมากบนเซิร์ฟเวอร์ระยะไกล (สคริปต์) โดยไม่มีผลกระทบใด ๆ แต่ต่อมาฉันได้อัปเดต JQuery lib เป็น 1.6.4 และทุกอย่างทำงานได้อย่างมีเสน่ห์


Whoopps ไม่ใช่ใน Opera 10.61 การตัดสินใจครั้งสุดท้ายของฉันในการทำเช่นนี้คือการใช้พรอกซี PHP ในโดเมนของฉัน
BasTaller

คุณใช้พร็อกซี PHP ได้อย่างไร คุณช่วยแนะนำฉันได้ไหม
Zoran777

ดูคำตอบด้านล่างเช่นโดย Ivan Durst
BasTaller

5

หากคุณต้องการทำสิ่งนี้ในสภาพแวดล้อม ASP.net MVC กับ JQuery AJAX ให้ทำตามขั้นตอนเหล่านี้: (นี่เป็นบทสรุปของการแก้ปัญหาที่เสนอที่นี่หัวข้อ )

สมมติว่า "caller.com" (สามารถเป็นเว็บไซต์ใด ๆ ก็ได้) ต้องโพสต์ที่ "server.com" (แอปพลิเคชัน ASP.net MVC)

  1. ใน Web.config ของแอป "server.com" ให้เพิ่มหัวข้อต่อไปนี้:

      <httpProtocol>
          <customHeaders>
              <add name="Access-Control-Allow-Origin" value="*" />
              <add name="Access-Control-Allow-Headers" value="Content-Type" />
              <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
          </customHeaders>
      </httpProtocol>
  2. ใน "server.com" เราจะดำเนินการต่อไปนี้บนคอนโทรลเลอร์ (เรียกว่า "Home") ซึ่งเราจะโพสต์:

    [HttpPost]
    public JsonResult Save()
    {
        //Handle the post data...
    
        return Json(
            new
            {
                IsSuccess = true
            });
    }
  3. จากนั้นจาก "caller.com" โพสต์ข้อมูลจากแบบฟอร์ม (ด้วย html id "formId") ไปยัง "server.com" ดังต่อไปนี้:

    $.ajax({
            type: "POST",
            url: "http://www.server.com/home/save",
            dataType: 'json',
            crossDomain: true,
            data: $(formId).serialize(),
            success: function (jsonResult) {
               //do what ever with the reply
            },
            error: function (jqXHR, textStatus) {
                //handle error
            }
        });

4

มีอีกวิธีหนึ่งคือ (ใช้คุณสมบัติ html5) คุณสามารถใช้พร็อกซี iframe ที่โฮสต์บนโดเมนอื่นนั้นคุณส่งข้อความโดยใช้ postMessage ไปยัง iframe นั้นจากนั้น iframe สามารถทำคำขอ POST (ในโดเมนเดียวกัน) และ postMessage กลับพร้อม reposnse ไปที่หน้าต่างหลัก

ผู้ปกครองใน sender.com

var win = $('iframe')[0].contentWindow

function get(event) {
    if (event.origin === "http://reciver.com") {
        // event.data is response from POST
    }
}

if (window.addEventListener){
    addEventListener("message", get, false)
} else {
    attachEvent("onmessage", get)
}
win.postMessage(JSON.stringify({url: "URL", data: {}}),"http://reciver.com");

iframe บน reciver.com

function listener(event) {
    if (event.origin === "http://sender.com") {
        var data = JSON.parse(event.data);
        $.post(data.url, data.data, function(reponse) {
            window.parent.postMessage(reponse, "*");
        });
    }
}
// don't know if we can use jQuery here
if (window.addEventListener){
    addEventListener("message", listener, false)
} else {
    attachEvent("onmessage", listener)
}

มีคำถามที่เกี่ยวข้องคือstackoverflow.com/questions/38940932/... เป็นไปได้ไหมที่จะสร้างปลั๊กอินหรือฟังก์ชั่นทั่วไปตามตัวอย่างของคุณ?
Andrus

@Andrus อาจจะเป็นแบบนี้gist.github.com/jcubic/26f806800abae0db9a0dfccd88cf6f3c
jcubic

รหัสนี้ต้องการการแก้ไขหน้าผู้รับ วิธีอ่านการตอบสนองหากหน้าตัวรับไม่สามารถแก้ไขได้
Andrus

@ อย่างไรก็ตามคุณไม่สามารถเข้าถึง recever.com iframe เพื่อส่งคำขอ ajax ที่นั่นได้ หากไม่มี iframe จะไม่มีการร้องขอ
jcubic

3

ระดับสูง .... คุณต้องมีการตั้งค่า cname บนเซิร์ฟเวอร์ของคุณเพื่อให้ other-serve.your-server.com ของคุณชี้ไปที่ other-server.com

หน้าของคุณสร้าง iframe ที่มองไม่เห็นแบบไดนามิกซึ่งทำหน้าที่เป็นระบบขนส่งของคุณไปยัง other-server.com จากนั้นคุณต้องสื่อสารผ่าน JS จากหน้าของคุณไปยัง other-server.com และมีการโทรกลับที่ส่งคืนข้อมูลกลับไปที่หน้าของคุณ

เป็นไปได้ แต่ต้องมีการประสานงานจาก your-server.com และ other-server.com


ไม่เคยคิดที่จะใช้ CNAME เพื่อเปลี่ยนเส้นทาง โทรดี! ฉันยังไม่ได้ลอง แต่ฉันคิดว่า CNAME จะหลอกเบราว์เซอร์ให้คิดว่ามันโต้ตอบกับไซต์เดียวกันหรือไม่ ฉันจะใช้มันเพื่อโพสต์ไปที่ Amazon S3 ดังนั้นฉันจึงหวังว่ามันจะใช้ได้
SpencerElliott

1
ฉันไม่เห็นว่ามันจะแก้ปัญหาอะไร การข้ามไปยังโดเมนย่อยอื่นมีปัญหาเช่นเดียวกับการข้ามไปยังโดเมนอื่น
Octopus


2

นี่เป็นคำถามเก่า แต่เทคโนโลยีใหม่บางอย่างอาจช่วยใครซักคน

หากคุณมีสิทธิ์การเข้าถึงระดับผู้ดูแลระบบไปยังเซิร์ฟเวอร์อื่นคุณสามารถใช้โครงการ opensource Forge เพื่อทำ POST ข้ามโดเมนได้ Forge จัดเตรียม JavaScript XmlHttpRequest wrapper ของ cross-domain ที่ใช้ประโยชน์จาก raw socket API ของ Flash POST สามารถทำได้ผ่าน TLS

เหตุผลที่คุณต้องการสิทธิ์การเข้าถึงระดับผู้ดูแลระบบไปยังเซิร์ฟเวอร์ที่คุณกำลังทำรายการอยู่นั้นเป็นเพราะคุณต้องระบุนโยบายข้ามโดเมนที่อนุญาตการเข้าถึงจากโดเมนของคุณ

http://github.com/digitalbazaar/forge


2

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันต้องการแบ่งปันวิธีการของฉัน ฉันใช้ cURL เป็นพร็อกซี่ง่ายและสอดคล้องกันมาก สร้างหน้า php ชื่อ submit.php และเพิ่มรหัสต่อไปนี้:

<?

function post($url, $data) {
$header = array("User-Agent: " . $_SERVER["HTTP_USER_AGENT"], "Content-Type: application/x-www-form-urlencoded");
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}

$url = "your cross domain request here";
$data = $_SERVER["QUERY_STRING"];
echo(post($url, $data));

จากนั้นใน js ของคุณ (jQuery ที่นี่):

$.ajax({
type: 'POST',
url: 'submit.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
    var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
    alert('POST failed.');
}
});

1

ควรเป็นไปได้ด้วยตารางที่กำหนดเอง YQL + JS XHR ลองดูที่: http://developer.yahoo.com/yql/guide/index.html

ฉันใช้เพื่อทำการขูด html ฝั่งไคลเอ็นต์ (js) ใช้งานได้ดี (ฉันมีเครื่องเล่นเสียงเต็มรูปแบบพร้อมค้นหาบนอินเทอร์เน็ต / เพลย์ลิสต์ / เนื้อเพลง / ข้อมูล fm ล่าสุดไคลเอนต์ js + YQL ทั้งหมด)


1

CORS สำหรับคุณ CORS คือ "Cross Origin Resource Sharing" เป็นวิธีการส่งคำขอข้ามโดเมนตอนนี้ XMLHttpRequest2 และ Fetch API รองรับทั้ง CORS และสามารถส่งคำขอ POST และ GET

แต่มันมีข้อ จำกัด เซิร์ฟเวอร์จำเป็นต้องอ้างสิทธิ์เฉพาะเจาะจงว่าAccess-Control-Allow-Originและไม่สามารถตั้งค่าเป็น '*'

และหากคุณต้องการให้ต้นกำเนิดใด ๆ สามารถส่งคำขอถึงคุณได้คุณต้องมี JSONP (ต้องตั้งค่าการควบคุมการอนุญาตให้กำเนิดแต่ต้องเป็น '*')

สำหรับวิธีการร้องขอมากมายหากคุณไม่ทราบวิธีการเลือกฉันคิดว่าคุณต้องมีองค์ประกอบการทำงานเต็มรูปแบบที่จะทำเช่นนั้นให้ฉันแนะนำองค์ประกอบง่าย ๆhttps://github.com/Joker-Jelly/catta


หากคุณกำลังใช้เบราว์เซอร์ที่ทันสมัย ​​(> IE9, Chrome, FF, Edge และอื่น ๆ ) ขอแนะนำให้คุณใช้องค์ประกอบที่เรียบง่าย แต่สวยงามที่https://github.com/Joker-Jelly/cattaไม่มีการพึ่งพา กว่า 3KB และรองรับ Fetch, AJAX และ JSONP ด้วยไวยากรณ์และตัวอย่างตัวเลือกที่เหมือนกัน

catta('./data/simple.json').then(function (res) {
  console.log(res);
});

นอกจากนี้ยังรองรับการนำเข้าสู่โครงการของคุณเช่นโมดูล ES6, CommonJS และแม้แต่<script>ใน HTML


1

หากคุณสามารถเข้าถึงเซิร์ฟเวอร์ข้ามโดเมนและไม่ต้องการเปลี่ยนแปลงรหัสใด ๆ ในฝั่งเซิร์ฟเวอร์คุณสามารถใช้ไลบรารีที่เรียกว่า - 'xdomain'

มันทำงานอย่างไร:

ขั้นตอนที่ 1: เซิร์ฟเวอร์ 1: รวมไลบรารี xdomain และกำหนดค่า cross domain เป็นสลาฟ:

<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>

ขั้นตอนที่ 2: บนเซิร์ฟเวอร์ข้ามโดเมนสร้างไฟล์ proxy.html และรวมเซิร์ฟเวอร์ 1 เป็นหลัก:

proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
  xdomain.masters({
    "https://server1" : '*'
  });
</script>

ขั้นตอนที่ 3:

ตอนนี้คุณสามารถโทร AJAX ไปที่ proxy.html เป็น endpoint จาก server1 นี่คือการข้ามการร้องขอ CORS ไลบรารีใช้โซลูชัน iframe ภายในซึ่งทำงานกับหนังสือรับรองและวิธีการที่เป็นไปได้ทั้งหมด: GET, POST ฯลฯ

สอบถามรหัส ajax:

$.ajax({
        url: 'https://crossdomain_server/proxy.html',
        type: "POST",
        data: JSON.stringify(_data),
        dataType: "json",
        contentType: "application/json; charset=utf-8"
    })
    .done(_success)
    .fail(_failed)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.