إضافة دعم CORS إلى خادم وكيل لواجهة برمجة التطبيقات

يتم الآن عرض مستندات Apigee Edge.
انتقِل إلى مستندات Apigee X.
المعلومات

إنّ CORS (مشاركة الموارد المتعدّدة المصادر) هي آلية عادية تسمح لاستدعاءات XMLHttpRequest (XHR) بلغة JavaScript التي يتم تنفيذها في صفحة الويب بالتفاعل مع الموارد من نطاقات غير المصدر. إنّ سياسة مشاركة الموارد المتعددة المصادر (CORS) هي حل يتم تنفيذه بشكل شائع مع "سياسة المصدر نفسه" التي يتم فرضها من خلال جميع المتصفحات. على سبيل المثال، إذا أجريت طلب XHR لواجهة برمجة تطبيقات Twitter من خلال رمز JavaScript يتم تنفيذه في المتصفّح، لن ينجح الطلب. ويرجع ذلك إلى أنّ النطاق الذي يعرض الصفحة في متصفّحك يختلف عن النطاق الذي يعرض واجهة برمجة تطبيقات Twitter. توفّر سياسة مشاركة الموارد المتعددة المصادر (CORS) حلاً لهذه المشكلة من خلال السماح للخوادم "بتفعيل" إذا كانت تريد إتاحة مشاركة الموارد من مصادر متعددة.

فيديو: يمكنك مشاهدة فيديو قصير للتعرّف على كيفية تفعيل سياسة مشاركة الموارد المتعددة المصادر (CORS) على خادم وكيل لواجهة برمجة التطبيقات.

حالة الاستخدام النموذجية لـ 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 يستدعي واجهة برمجة تطبيقات الخدمة على الواجهة الخلفية. تذكَّر أنّ Edge يقع بين البرنامج (متصفّح في هذه الحالة) وواجهة برمجة التطبيقات في الخلفية (الخدمة). بما أنّ الخادم الوكيل لواجهة برمجة التطبيقات يعمل على الخادم وليس في المتصفّح، يمكنه طلب الخدمة بنجاح. بعد ذلك، ما عليك سوى إرفاق عناوين CORS باستجابة TargetEndpoint. وعندما يتوافق المتصفّح مع سياسة مشاركة الموارد المتعددة المصادر (CORS)، تشير هذه العناوين إلى المتصفّح بأنّه يمكن "استرخاء" سياسة المصدر نفسه، ما يسمح بنجاح بطلب البيانات من واجهة برمجة التطبيقات المتعددة المصادر.

بعد إنشاء الخادم الوكيل الذي يتوافق مع سياسة CORS، يمكنك طلب عنوان URL للخادم الوكيل لواجهة برمجة التطبيقات بدلاً من خدمة الخلفية في الرمز من جهة العميل. مثلاً:

<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 بخادم وكيل جديد لواجهة برمجة التطبيقات

يمكنك إضافة دعم CORS إلى خادم وكيل لواجهة برمجة التطبيقات من خلال إرفاق سياسة "إضافة CORS" بالخادم الوكيل لواجهة برمجة التطبيقات عند إنشائه. لإضافة هذه السياسة، ضَع علامة في مربّع الاختيار إضافة عناوين CORS في صفحة "الأمان" في معالج إنشاء خادم وكيل.

عند وضع علامة في مربّع الاختيار هذا، تتم تلقائيًا إضافة سياسة باسم "إضافة سياسة مشاركة الموارد المتعدّدة المصادر (CORS)" إلى النظام ويتم إرفاقها بالمسار السابق لاستجابة نقطة النهاية، كما هو موضّح في الشكل التالي:

إضافة سياسة CORS إلى أداة التنقّل ضمن &quot;السياسات&quot; وإرفاقها بالتدفق السابق لاستجابة 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 للخادم الوكيل لواجهة برمجة التطبيقات. يمكنك تعديل قيم العناوين حسب الحاجة. لمزيد من المعلومات عن إنشاء السياسات وإرفاقها، يمكنك الاطّلاع على المقالة ما هي السياسة؟.

التعامل مع طلبات الطلب المبدئي 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 هذه:

  • يتم إنشاء قاعدة مسار إلى هدف فارغ مع شرط لطلب OPTIONS. تجدر الإشارة إلى أنّه لم يتم تحديد TargetEndpoint. إذا تم استلام طلب OPTIONS ولم تكن عناوين طلبات المصدر و"طريقة طلب الوصول للتحكم في الوصول" فارغة، سيعرض الخادم الوكيل على الفور عناوين CORS كاستجابة للبرنامج (متجاوزًا هدف "الخلفية" التلقائي). للحصول على تفاصيل عن ظروف التدفق وRoute مباشرةً، يُرجى الاطِّلاع على الشروط التي تتضمّن متغيّرات التدفق.

    <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. يمكنك استيراد حزمة التدفق المشترك إلى بيئتك وإرفاقها باستخدام تدفقات التدفق أو مباشرةً إلى تدفقات الخادم الوكيل لواجهة برمجة التطبيقات. لمعرفة التفاصيل، يُرجى الاطّلاع على ملف CORS-Shared-FLow README المتوفّر مع النموذج.