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

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

عناوين 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: قراءة عنوان "قبول" متعدد القيم باستخدام رمز 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 أو PrepareFault

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

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

في ما يلي جزء الرمز من سياسة AssignMessage أو riseFault لإعداد عنوان 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.

    مثال: نموذج رمز 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 في سياسة AcceleratedFault أو AssignMessage لقراءة جميع قيم عنوان معيّن.

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

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

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