Antipattern: الوصول إلى رؤوس HTTP متعددة القيم بشكل غير صحيح في خادم وكيل لواجهة برمجة التطبيقات

أنت الآن بصدد الاطّلاع على مستندات Apigee Edge.
انتقِل إلىمستندات Apigee X.
info

عناوين HTTP هي أزواج الاسم والقيمة التي تسمح لتطبيقات العميل وخدمات الخلفية بتمرير معلومات إضافية عن الطلبات والردود على التوالي. في ما يلي بعض الأمثلة البسيطة:

  • يمرّر عنوان طلب التفويض بيانات اعتماد المستخدم إلى الخادم:
    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
  • يشير عنوان Content-Type إلى نوع محتوى الطلب/الرد الذي يتم إرساله:
    Content-Type: application/json

يمكن أن تحتوي عناوين HTTP على قيمة واحدة أو أكثر استنادًا إلى تعريفات حقول العنوان. سيحتوي العنوان المتعدد القيم على قيم مفصولة بفواصل. في ما يلي بعض الأمثلة على العناوين التي تحتوي على قيم متعددة:

  • Cache-Control: no-cache, no-store, must-revalidate
  • Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
  • X-Forwarded-For: 10.125.5.30, 10.125.9.125

يسمح Apigee Edge للمطوّرين بالوصول إلى العناوين بسهولة باستخدام متغيّرات التدفق في أي من سياسات Edge أو عمليات التدفق الشرطية. في ما يلي قائمة بالمتغيّرات التي يمكن استخدامها للوصول إلى عنوان طلب أو عنوان الاستجابة معيّن في Edge:

متغيّرات التدفق:

  • message.header.header-name
  • request.header.header-name
  • response.header.header-name
  • message.header.header-name.N
  • request.header.header-name.N
  • response.header.header-name.N

كائنات JavaScript:

  • context.proxyRequest.headers.header-name
  • context.targetRequest.headers.header-name
  • context.proxyResponse.headers.header-name
  • context.targetResponse.headers.header-name

في ما يلي نموذج لسياسة AssignMessage يوضّح كيفية قراءة قيمة عنوان طلب وتخزينها في متغيّر:

<AssignMessage continueOnError="false" enabled="true" name="assign-message-default">
  <AssignVariable>
    <Name>reqUserAgent</Name>
    <Ref>request.header.User-Agent</Ref>
  </AssignVariable>
</AssignMessage>

نمط غير مستحسن

إنّ الوصول إلى قيم عناوين HTTP في سياسات Edge بطريقة لا تعرض سوى القيمة الأولى غير صحيح ويمكن أن يؤدي إلى حدوث مشاكل إذا كان لعنوان HTTP معيّن أكثر من قيمة واحدة.

تحتوي الأقسام التالية على أمثلة على الوصول إلى العناوين.

المثال 1: قراءة عنوان Accept متعدد القيم باستخدام رمز JavaScript

لنفترض أنّ عنوان Accept يحتوي على قيم متعددة كما هو موضّح أدناه:

Accept: text/html, application/xhtml+xml, application/xml

في ما يلي رمز JavaScript الذي يقرأ القيمة من عنوان Accept:

// Read the values from Accept header
var acceptHeaderValues = context.getVariable("request.header.Accept");

لا يعرض رمز JavaScript أعلاه سوى القيمة الأولى من عنوان Accept، مثل text/html.

المثال 2: قراءة عنوان Access-Control-Allow-Headers متعدد القيم في سياسة AssignMessage أو RaiseFault

لنفترض أنّ عنوان Access-Control-Allow-Headers يحتوي على قيم متعددة كما هو موضّح أدناه:

Access-Control-Allow-Headers: content-type, authorization

في ما يلي جزء من الرمز من سياسة AssignMessage أو RaiseFault التي تضبط عنوان Access-Control-Allow-Headers:

<Set>
  <Headers>
    <Header name="Access-Control-Allow-Headers">{request.header.Access-Control-Request-Headers}</Header>
  </Headers>
</Set>

يضبط الرمز أعلاه العنوان Access-Control-Allow-Headers بالقيمة الأولى فقط من عنوان الطلب Access-Control-Allow-Headers، وفي هذا المثال content-type.

التأثير

  1. في كلا المثالَين أعلاه، يُرجى العِلم أنّه يتم عرض القيمة الأولى فقط من العناوين المتعددة القيم. إذا تم استخدام هذه القيم لاحقًا من قِبل سياسة أخرى في تدفق خادم وكيل واجهة برمجة التطبيقات أو من قِبل خدمة الخلفية لتنفيذ بعض الوظائف أو المنطق، فقد يؤدي ذلك إلى نتيجة غير متوقّعة.
  2. عند الوصول إلى قيم عناوين الطلبات وتمريرها إلى الخادم الوجهة، يمكن أن تعالج خدمة الخلفية طلبات واجهة برمجة التطبيقات بشكل غير صحيح، وبالتالي قد تقدّم نتائج غير صحيحة.
  3. إذا كان تطبيق العميل يعتمد على قيم عناوين معيّنة من ردّ Edge، فقد تتم أيضًا معالجته بشكل غير صحيح وتقديم نتائج غير صحيحة.

أفضل الممارسات

  1. استخدِم متغيّرات التدفق المضمّنة المناسبة: request.header.header_name.values.count و request.header.header_name.N وresponse.header.header_name.values.count و response.header.header_name.N.

    بعد ذلك، كرِّر عملية جلب جميع القيم من عنوان معيّن في سياسات JavaScript أو Java callout.

    مثال: نموذج لرمز JavaScript لقراءة عنوان متعدد القيم

    for (var i = 1; i <=context.getVariable('request.header.Accept.values.count'); i++)
    {
      print(context.getVariable('request.header.Accept.' + i));
    }

    على سبيل المثال، سيظهر application/xml;q=0.9, */*;q=0.8 كقيمة واحدة باستخدام الرمز أعلاه.

    إذا كان يجب تقسيم قيم العنوان باستخدام الفاصلة المنقوطة كمحدّد، استخدِم string.split(";") لفصل هذه القيم.

  2. استخدِم الدالة substring() على متغيّر التدفق request.header.header_name.values في سياسة RaiseFault أو AssignMessage لقراءة جميع قيم عنوان معيّن.

    مثال: نموذج لسياسة RaiseFault أو AssignMessage لقراءة عنوان متعدد القيم

    <Set>
      <Headers>
       <Header name="Access-Control-Allow-Headers">{substring(request.header.Access-Control-Request-Headers.values,1,-1)}</Header>
      </Headers>
    </Set>

محتوى إضافي للقراءة