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

הנה דוגמה למדיניות AssignedMessage, שמראה איך לקרוא את הערך של כותרת בקשה ולאחסן אותה במשתנה:

<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 או 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. בשתי הדוגמאות שלמעלה, שימו לב שרק הערך הראשון מכותרות עם ערכים מרובים מוחזר. אם בהמשך נעשה שימוש בערכים האלה במדיניות אחרת בתהליך ה-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 במדיניות 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>
    

קריאה נוספת