การเพิ่มการรองรับ CORS ไปยังพร็อกซี API

คุณกำลังดูเอกสารประกอบ Apigee Edge
ไปที่ เอกสารประกอบเกี่ยวกับ Apigee X.
ข้อมูล

CORS (การแชร์ทรัพยากรข้ามต้นทาง) เป็นกลไกมาตรฐานที่อนุญาต JavaScript การเรียกใช้ XMLHttpRequest (XHR) ที่ดำเนินการในหน้าเว็บเพื่อโต้ตอบกับทรัพยากรจากแหล่งที่มาที่ไม่ใช่ต้นทาง โดเมน CORS เป็นโซลูชันที่ใช้งานกันโดยทั่วไปสำหรับ "นโยบายต้นทางเดียวกัน" ที่บังคับใช้โดย ทุกเบราว์เซอร์ ตัวอย่างเช่น หากคุณเรียก XHR ไปยัง Twitter API จากโค้ด JavaScript ขณะดำเนินการในเบราว์เซอร์ การเรียกใช้จะล้มเหลว เนื่องจากโดเมนที่ให้บริการหน้าเว็บ เบราว์เซอร์ของคุณไม่เหมือนกับโดเมนที่ใช้ Twitter API CORS มีโซลูชันสำหรับ ปัญหานี้ได้โดยการอนุญาตให้เซิร์ฟเวอร์ "เลือกใช้" หากต้องการจัดหาทรัพยากรแบบข้ามต้นทาง การแชร์

วิดีโอ: ดูวิดีโอสั้นๆ เพื่อดูวิธีเปิดใช้ CORS บนพร็อกซี API

กรณีการใช้งานทั่วไปสำหรับ CORS

โค้ด JQuery ต่อไปนี้เรียกใช้บริการเป้าหมายที่สมมติขึ้น หากดำเนินการจากภายใน บริบทของเบราว์เซอร์ (หน้าเว็บ) การเรียกจะล้มเหลวเนื่องจากนโยบายต้นทางเดียวกัน ได้แก่

<script>
var url = "http://service.example.com";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This is where we end up!
            }
    });
  });
});
</script>

วิธีแก้ไขอย่างหนึ่งคือสร้างพร็อกซี Apigee API ที่เรียกใช้ API ของบริการใน ระบบแบ็กเอนด์ โปรดทราบว่า Edge อยู่ระหว่างไคลเอ็นต์ (ในกรณีนี้คือเบราว์เซอร์) และแบ็กเอนด์ API (บริการ) เนื่องจากพร็อกซี API จะทำงานบนเซิร์ฟเวอร์ ไม่ใช่ในเบราว์เซอร์ สามารถเรียกใช้บริการได้สําเร็จ จากนั้นสิ่งที่คุณต้องทำ แนบส่วนหัว CORS กับการตอบกลับ TargetEndpoint ถ้าเบราว์เซอร์รองรับ CORS ส่วนหัวเหล่านี้จะส่งสัญญาณให้เบราว์เซอร์ทราบว่าสามารถ "ผ่อนคลาย" ได้ นโยบายต้นทางเดียวกัน การเรียก API แบบข้ามต้นทางให้ประสบความสำเร็จ

เมื่อสร้างพร็อกซีที่มีการสนับสนุน CORS แล้ว คุณสามารถเรียกใช้ URL พร็อกซี API แทนการเรียก ในโค้ดฝั่งไคลเอ็นต์ของคุณ เช่น

<script>
var url = "http://myorg-test.apigee.net/v1/example";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This time, we do not end up here!
            }
    });
  });
});
</script>

การแนบนโยบาย CORS กับ API ใหม่ พร็อกซี

คุณเพิ่มการรองรับ CORS ไปยังพร็อกซี API ได้โดยแนบ "เพิ่ม CORS" นโยบายกับพร็อกซี API เมื่อคุณสร้าง หากต้องการเพิ่มนโยบายนี้ ให้เลือกช่องทำเครื่องหมายเพิ่มส่วนหัว CORS ใน หน้าความปลอดภัยของวิซาร์ดสร้างพร็อกซี

เมื่อเลือกช่องทำเครื่องหมายนี้ ระบบจะเพิ่มนโยบายชื่อ "เพิ่ม CORS" ลงในระบบโดยอัตโนมัติ และแนบกับขั้นตอนการตอบสนองล่วงหน้าของ TargetEndpoint ดังที่แสดงในรูปต่อไปนี้

เพิ่มนโยบาย CORS ที่เพิ่มในตัวนำทางภายใต้นโยบายและแนบกับขั้นตอนก่อนการตอบกลับของ TargetEndpoint ในการเลื่อนด้านขวา

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

คุณควรแก้ไขนโยบายดังต่อไปนี้

  • เพิ่มส่วนหัว content-type และ authorization (ซึ่งจำเป็นเพื่อรองรับการตรวจสอบสิทธิ์พื้นฐานหรือ OAuth2) ไปยังส่วนหัว Access-Control-Allow-Headers ดังที่แสดงในข้อความที่ตัดตอนมาจากโค้ดด้านล่าง
  • สำหรับการตรวจสอบสิทธิ์ OAuth2 คุณอาจต้องทำตามขั้นตอนเพื่อแก้ไขการทำงานที่ไม่เป็นไปตามข้อกำหนด RFC
  • เราขอแนะนำให้ใช้ <Set> เพื่อตั้งค่าส่วนหัว CORS แทน <Add> ดังที่แสดงในข้อความที่ตัดตอนมาด้านล่าง เมื่อใช้ <Add> หากมีส่วนหัว Access-Control-Allow-Origin อยู่แล้ว คุณจะได้รับข้อผิดพลาดต่อไปนี้

    The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

    สำหรับข้อมูลเพิ่มเติม โปรดดู ข้อผิดพลาด CORS : ส่วนหัวมีค่า "*, *" หลายค่า แต่อนุญาตให้มีได้เพียงค่าเดียว

<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <FaultRules/>
    <Properties/>
    <Set>
        <Headers>
            <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, authorization</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

การเพิ่มส่วนหัว CORS ไปยังพร็อกซีที่มีอยู่

คุณต้องสร้างนโยบายมอบหมายข้อความใหม่ด้วยตนเองและคัดลอกโค้ดสําหรับเพิ่ม CORS ที่ระบุไว้ในส่วนก่อนหน้า จากนั้นแนบนโยบายกับขั้นตอนการตอบกลับล่วงหน้าของ TargetEndpoint ของพร็อกซี API คุณสามารถแก้ไขค่าส่วนหัวได้ตามต้องการ สำหรับข้อมูลเพิ่มเติม ข้อมูลเกี่ยวกับการสร้างและการแนบนโยบาย โปรดดูที่นโยบายคืออะไร

การจัดการ CORS คำขอการตรวจสอบล่วงหน้า

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

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบล่วงหน้าได้ที่คำแนะนำ W3C การแชร์ทรัพยากรข้ามโดเมน มี ใน นอกจากนี้ยังมีบล็อกและบทความเกี่ยวกับ CORS ที่คุณสามารถอ้างถึงได้

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

มาดูขั้นตอนตัวอย่างแล้วพูดคุยถึงส่วนต่างๆ ที่จัดการคำขอตรวจสอบล่วงหน้ากัน

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows>
        <Flow name="OptionsPreFlight">
            <Request/>
            <Response>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </Response>
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
        </Flow>
    </Flows>

    <PreFlow name="PreFlow">
        <Request/>
        <Response/>

    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/v1/cnc</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
   </RouteRule>
   <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</ProxyEndpoint>

ส่วนสำคัญของ ProxyEndpoint มีดังนี้

  • ระบบจะสร้าง RouteRule ไปยังเป้าหมาย NULL ที่มีเงื่อนไขสำหรับคำขอ OPTIONS โปรดทราบว่า ไม่มีการระบุ TargetEndpoint หากได้รับคำขอ OPTIONS และต้นทางและ ส่วนหัวของคำขอ Access-Control-Request-Method ไม่เป็นค่าว่าง พร็อกซีจะแสดงผล ส่วนหัว CORS ในการตอบกลับไคลเอ็นต์ (ข้ามเป้าหมาย "แบ็กเอนด์" เริ่มต้นจริง) โปรดดูรายละเอียดเกี่ยวกับเงื่อนไขโฟลว์และ RouteRule ที่หัวข้อเงื่อนไขที่มีตัวแปรโฟลว์

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • สร้างขั้นตอน OptionsPreFlight ที่เพิ่มนโยบาย CORS ที่มี CORS ไปยังโฟลว์หากได้รับคำขอ OPTIONS และต้นทางและ ส่วนหัวของคำขอ Access-Control-Request-Method ไม่เป็นค่าว่าง

     <Flow name="OptionsPreFlight">
                <Request/>
                <Response>
                    <Step>
                        <Name>add-cors</Name>
                    </Step>
                </Response>
            <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
     </Flow>
    

การใช้โซลูชัน CORS ตัวอย่าง

มีตัวอย่างโซลูชัน CORS ที่ใช้งานเป็นขั้นตอนที่ใช้ร่วมกันให้บริการใน GitHub นำเข้าแพ็กเกจโฟลว์ที่แชร์ไปยังสภาพแวดล้อม และแนบโดยใช้โฟลว์ฮุกหรือกับโฟลว์พร็อกซี API โดยตรง โปรดดูรายละเอียดที่ ไฟล์ CORS-Shared-FLow README ที่ให้มาพร้อมตัวอย่าง