Antipattern: גישה שגויה לכותרות HTTP עם ערכים מרובים בשרת proxy ל-API

מוצג המסמך של 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 או IncreaseFault

שימו לב שלכותרת Access-Control-Allow-Headers יש כמה ערכים, כפי שמוצג בהמשך:

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

זהו החלק של הקוד ממדיניות AssignMessage או IncreaseFault, שמגדיר את הכותרת 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. בשתי הדוגמאות שלמעלה, שימו לב שמוחזר רק הערך הראשון מכותרות מרובות ערכים. אם הערכים האלה ישמשו בהמשך מדיניות אחרת בתהליך ה-API של ה-Proxy או בשירות לקצה העורפי כדי לבצע פונקציה או לוגיקה כלשהי, היא עלולה להוביל לתוצאה או לתוצאה לא צפויה.
  2. כשניגשים לערכים של כותרות הבקשה ומועברים לשרת היעד, ניתן לבצע בקשות API מעובדות על ידי הקצה העורפי בצורה שגויה, ולכן הן עלולות לתת תוצאות שגויות.
  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 במדיניות IncreaseFault או AssignMessage כדי לקרוא את כל הערכים של כותרת ספציפית.

    דוגמה: דוגמאות של IncreaseFault או מדיניות AssignMessage לקריאת כותרת עם ערכים מרובים

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

קריאה נוספת