תנאים עם משתני זרימה

אתם צופים במסמכי העזרה של Apigee Edge.
עוברים אל מסמכי תיעוד של Apigee X.
מידע

הצהרות מותנות הן מבנה בקרה נפוץ בכל שפות התכנות. לסמן לייק על שפת תכנות, הגדרת שרת proxy ל-API תומכת בהצהרות מותנות ל-Fflows, מדיניות, שלבים וכללי נתיב. הגדרת הצהרות תנאי מאפשרת לכם להגדיר התנהגות דינמית של ה-API. ההתנהגות הדינמית הזו מאפשרת לבצע פעולות כמו המרת XML ל-JSON רק לצורך מכשירים ניידים, או ניתוב לכתובת URL של קצה עורפי על סמך סוג התוכן או פועל ה-HTTP של הבקשה הודעה.

כאן נסביר איך משתמשים בתנאים כדי להחיל באופן דינמי תכונות של ניהול ממשקי API בזמן הריצה, בלי לכתוב קוד.

הגדרת תנאים

התנהגות מותנית מיושמת בשרתים proxy של API באמצעות שילוב של תנאים ומשתנים. הצהרה מותנית נוצרת באמצעות הרכיב Condition. התנאי הבא הוא תנאי ריק:

<Condition></Condition>

כדי ליצור הצהרת תנאי, צריך להוסיף אופרטור מותנה ומשתנה כדי ליצור את במבנה הבא:

<Condition>{variable.name}{operator}{"value"}</Condition>

האופרטורים המותנים הנתמכים כוללים = (שווה ל-), != (לא שווה) ו-> (גדול מ-). כדי שקל יהיה לקרוא את הקוד, אפשר גם לכתוב את התנאים כטקסט: equals, notequals, greaterthan.

כשעובדים עם נתיבי URI, אפשר להשתמש ב-~/ או ב-MatchesPath. אפשר גם להתאים ביטויים רגולריים של JavaRegex באמצעות המפעיל ~~.

התנאים משמשים להגדרת תהליכים מותנים בשרת proxy ל-API למשאבי API לקצה העורפי, כפי שמתואר במאמר יצירת תהליכי עבודה מותנים למשאבי API לקצה העורפי. רשימה מלאה של תנאים זמינה במאמר חומר עזר בנושא תנאים.

משתנים

התנאים פועלים על ידי הערכת הערכים של variables. משתנה הוא מאפיין של עסקת HTTP שמתבצעת על ידי שרת proxy של API, או מאפיין של הגדרת שרת proxy של API עצמו. בכל פעם ששרת proxy ל-API מקבל בקשה מאפליקציה, Apigee Edge מאכלס רשימה ארוכה של משתנים שמשויכים לדברים כמו שעון המערכת, פרטי הרשת של האפליקציה, כותרות HTTP בהודעות, ההגדרות של שרת ה-proxy ל-API, ביצוע המדיניות וכו'. כך נוצר הקשר עשיר שאפשר להשתמש בו כדי להגדיר משפטים מותנים.

משתנים תמיד משתמשים בסימון מקווקו. לדוגמה, כותרות HTTP בהודעת הבקשה זמינות כמשתנים שנקראים request.header.{header_name}. אז כדי להעריך את המודל כותרת של סוג תוכן, אפשר להשתמש במשתנה request.header.Content-type. עבור לדוגמה request.header.Content-type = "application/json" מציין שהתוכן סוג הבקשה צריך להיות JSON.

נניח שאתם צריכים ליצור הצהרה מותנית שתגרום למדיניות נאכף רק כאשר הודעת הבקשה היא GET. כדי ליצור תנאי שבודק את פעולת ה-HTTP של בקשה, יוצרים את התנאי המותנה הבא. המשתנה בתנאי הזה הוא request.verb. הערך של המשתנה הוא GET. המפעיל הוא =

<Condition>request.verb = "GET"</Condition>
אפשר גם להשתמש באפשרות הבאה:
<Condition>request.verb equals "GET"</Condition>

Edge משתמש בהצהרה כזו כדי להעריך את התנאים. הערך של הדוגמה שלמעלה הוא True אם פועל ה-HTTP המשויך לבקשה הוא GET. אם פועל ה-HTTP המשויך לבקשה הוא POST, אז ההצהרה מוערכת ל-False.

כדי להפעיל התנהגות דינמית, אפשר לצרף תנאים ל-flows, לשלבים ול-RouteRules.

כשמצרפים תנאי לתהליך, יוצרים 'תהליך מותנה'. תהליכים מותנים מתחילים לפעול רק כשהתנאי מקבל ערך TRUE. אפשר לצרף כמה כללי מדיניות שרוצים לתהליך מותנה. תהליך מותנה מאפשר ליצור כללי עיבוד ייחודיים מאוד עבור הודעות בקשה או תשובה שעומדות בקריטריונים מסוימים.

לדוגמה, כדי ליצור תהליך שפועל רק כאשר פועל הבקשה הוא GET:

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
</Flows>

כדי ליצור תהליך אחד לבקשות GET ותהליך נוסף ל-POST:

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
  <Flow name="ExecuteForPOSTs">
  <Condition>request.verb="POST"</Condition>
  </Flow>
</Flows>

כפי שמוצג בדוגמה הבאה, אפשר להחיל את התנאי על שלב המדיניות עצמו. התנאי הבא גורם לאכיפה של מדיניות VerifyApiKey רק אם הודעת בקשה POST.

<PreFlow name="PreFlow">
    <Request>
        <Step>
            <Condition>request.verb equals "POST"</Condition>
            <Name>VerifyApiKey</Name>
        </Step>
    </Request>
</PreFlow>

אחרי שמגדירים תהליכים מותנים כאלה, אפשר לצרף אליהם כללי מדיניות, וכך לאפשר לשרת proxy של API לאכוף קבוצת כללי מדיניות אחת לבקשות GET וקבוצת כללי מדיניות אחרת לבקשות POST.

תוכלו להיעזר במקורות המידע הבאים כדי לקבל מידע מקיף:

דוגמה 1

הדוגמה הבאה מציגה זרימה מותנה אחת בשם Convert-for-devices, שהוגדר בתהליך התגובה של ProxyEndpoint. מוסיפים את התנאי כאלמנט לישות שאליה חל התנאי. בדוגמה הזו, התנאי הוא רכיב של התהליך. לכן, התהליך יבוצע בכל פעם שההצהרה תתקבל כ-true.

<Flows>
  <Flow name="Convert-for-devices">
  <Condition>(request.header.User-Agent = "Mozilla")</Condition>
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

בכל בקשה שמתקבלת מאפליקציה, דפדפן Edge שומר את הערכים של כל כותרות ה-HTTP שנמצאות כ: משתנים. אם הבקשה כוללת כותרת HTTP שנקראת User-Agent, הכותרת והערך שלה מאוחסנים כמשתנה שנקרא request.header.User-Agent.

בהתאם להגדרה של ProxyEndpoint שלמעלה, Edge בודק את הערך של המשתנה request.header.User-Agent כדי לבדוק אם התנאי מקבל את הערך נכון.

אם התנאי מקבל את הערך True, הערך של המשתנה request.header.User-Agent שווה ל-Mozilla, ואז הזרימה המותנית מופעל, ומדיניות XMLtoJSON בשם ConvertToJSON נאכפת. אם לא, לא מבוצעת, ותגובת ה-XML מוחזרת ללא שינוי (בפורמט XML) אל הבקשה אפליקציה.

דוגמה 2

ניקח דוגמה ספציפית שבה צריך לשנות את הודעת התגובה מ-XML JSON – אבל רק עבור מכשירים ניידים. ראשית, יוצרים את המדיניות שתמיר את תגובה בפורמט XML מ-Weather API ל-JSON:

<XMLToJSON name="ConvertToJSON">
  <Options>
  </Options>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
</XMLToJSON>

הגדרת המדיניות שלמעלה מורה לשרת ה-proxy של ה-API לקחת את הודעת התגובה, לבצע המרה מ-XML ל-JSON עם הגדרות ברירת המחדל ואז לכתוב את התוצאה בהודעת התגובה החדשה. (אם אתם ממירים הודעת בקשה מ-XML ל-JSON, פשוט מגדירים את שני הערכים האלה ל-request).

כדי להמיר תשובות מ-XML ל-JSON, צריך להגדיר תנאי תגובה לביצוע ההמרה. לדוגמה, כדי להמיר את כל התשובות מ-XML ל-JSON לפני שהן מוחזרות לאפליקציית הלקוח, מגדירים את תהליך התגובה הבא של ProxyEndpoint.

<Flows>
  <Flow name="Convert-for-devices">
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

כשמפעילים את ה-API באמצעות הבקשה הרגילה, התשובה בפורמט JSON.

עם זאת, היעד שלכם הוא להמיר דוחות מזג אוויר ל-JSON רק כשהלקוח ששלח את הבקשה הוא מכשיר נייד. כדי לאפשר התנהגות דינמית כזו, צריך להוסיף תנאי ל-Flow.

בדיקת התהליך המותנה

בבקשה לדוגמה הזו, הכותרת User-Agent של HTTP מוגדרת כך Mozilla, כך שההצהרה המותנית תקבל את הערך True והתנאי המותנה זרימת Convert-for-devices כדי לבצע.

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

או, להדפיס יפה כאשר Python זמין:

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282 | python -mjson.tool

דוגמה לתגובה:

. . .

"yweather_forecast": [
         {
              "code": "11",
              "date": "12 Dec 2012",
              "day": "Wed",
              "high": "55",
              "low": "36",
              "text": "Showers"
          },
          {
              "code": "32",
              "date": "13 Dec 2012",
              "day": "Thu",
              "high": "56",
              "low": "38",
              "text": "Sunny"
          }
      ]
  }

. . .

בקשה שנשלחת בלי הכותרת User-Agent או עם ערך שונה מ-Mozilla תגרום לתגובה בפורמט XML.

$ curl http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

תגובת ה-XML המקורית מוחזר.

דוגמה לתשובה:

<yweather:forecast day="Wed" date="12 Dec 2012" low="36" high="55" text="Showers" code="11" /> <yweather:forecast day="Thu" date="13 Dec 2012" low="38" high="56" text="Sunny" code="32" />

התאמת דפוסים

בקטע הזה מוסבר איך משתמשים בהתאמה לתבנית עם תנאים בתהליך ב-Apigee.

אופרטורים

בקטע הזה מוסבר איך להשתמש באופרטורים הבאים להתאמת תבניות באופן מותנה הצהרות

התאמות

בואו נסתכל על העמודה 'התאמות' או '~' קודם האופרטור המותנה. שני האופרטורים האלה -- הגרסה באנגלית, "Matches", נחשבת לאפשרות קריאה יותר.

סיכום: ה"התאמות" נותן לך שתי אפשרויות. אחת מהאפשרויות מחרוזת מילולית, או התאמה של תו כללי לחיפוש עם "*". כפי שאפשר לצפות, התו הכללי לחיפוש תואם לאפס או יותר תווים. בואו נראה איך זה עובד.

.

ב-XML הבא מוצג תנאי של שלב. היא מפעילה את מדיניות somePolicy כשהתנאי הפונקציה מחזירה את הערך True. בדוגמה הזאת אנחנו בודקים את המשתנה proxy.pathsuffix, משתנה מובנה ב-Edge שמאחסן את סיומת הנתיב של הבקשה. עם זאת, חשוב לזכור שאפשר לבדוק את הערך של כל משתנה תהליך שמכיל מחרוזת. במקרה כזה, אם נתיב הבסיס של הבקשה הנכנסת הוא /animals והבקשה היא /animals/cat, הסיומת של הנתיב היא המחרוזת המילולית /cat.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix Matches "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

שאלה: איזה סיומת של נתיב שרת proxy תגרום להפעלה של SomePolicy? יש רק אפשרות אחת.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות פועלת? כן, כי הסיומת של נתיב שרת ה-proxy תואמת בדיוק ל-/cat. הפעולה לא תופעל אם הסיומת היא /bat או /dog, או '/' או כל דבר אחר.

עכשיו נבחן את ההצהרה המותנית שבה נשתמש בתו הכללי לחיפוש "*":

<Condition>(proxy.pathsuffix Matches "/*at")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות פועלת? כן, כי התו הכללי לחיפוש תואם לכל תו, וגם "/cat אינץ' יש התאמה.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/bat

האם המדיניות מופעלת? כן, כי התו הכללי לחיפוש תואם לכל תו, "/bat" יש התאמה.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/owl

האם המדיניות מופעלת? בהחלט לא – למרות שהתו הכללי לחיפוש תואם ל-"o", האותיות "wl" לא יהיו התאמות.

עכשיו נזיז את התו הכללי לסוף הסיומת:

<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות מופעלת? כן, כי התו הכללי לחיפוש תואם לאפס או יותר תווים כלשהם.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/bat

האם המדיניות פועלת? לא, "/bat" אין התאמה.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat123

האם המדיניות מופעלת? כן, התו הכללי לחיפוש תואם לאפס או יותר תווים כלשהם, לכן 123 יוצרת התאמה.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse

האם המדיניות מופעלת? כן, כי התו הכללי תואם לאפס תווים או יותר מכל תו, ולכן /bird/mouse יוצר התאמה. שימו לב איך ביטוי כמו זה יכול להכניס אתכם בעיה כי היא תואמת לכל מה שמופיע אחרי התווים המילוליים!

שאלה: האם האופרטור 'התאמות' תלוי אותיות רישיות (case-sensitive)?

כן. נניח שיש לכם תנאי כזה:

<Condition>(proxy.pathsuffix Matches "/*At")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות מופעלת? לא, התו הכללי לחיפוש תואם לכל אות (ללא קשר לאותיות רישיות), אבל 'a' קטנה לא תואם ל-"A".

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/bAt

האם המדיניות מופעלת? כן, יש התאמה.

שאלה: איך מוסיפים בתו בריחה (escape) תווים באמצעות האופרטור Matches?

שימוש באחוז '%' כדי לסמן בתו בריחה (escape) תווים שמורים. לדוגמה:

<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות מופעלת? לא, האופרטור Matches מחפש את המחרוזת המילולית "c*at".

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/c*at

שאלה:האם המדיניות מופעלת?

כן, הנתיב הזה, למרות שהוא קצת יוצא דופן, תואם.

JavaRegex

כפי שאפשר לראות, האופרטור 'התאמות' מתאים למצבים פשוטים. אבל אפשר להשתמש באופרטור אחר, האופרטור JavaRegex או האופרטור ~~. אלה אותם אופרטורים, אלא ש-JavaRegex נחשב קל יותר לקריאה. היא נקראת JavaRegex כי היא מאפשרת ביטוי רגולרי התאמת דפוסים, ו-Edge פועל לפי אותם כללים כמו המחלקות ב-java.util.regex. חבילה בשפת Java. אופן הפעולה של אופרטור JavaRegex שונה מאוד מאופן הפעולה של אופרטור Matches, לכן חשוב לא להתבלבל ביניהם.

סיכום: האופרטור JavaRegex מאפשר להשתמש בתחביר של ביטויים רגולריים במשפטי תנאי.

הקוד הבא מציג תנאי של שלב. המערכת מבצעת את המדיניות SomePolicy אם התנאי מקבל את הערך True. בדוגמה הזו אנחנו בודקים את המשתנה proxy.pathsuffix, משתנה מובנה ב-Edge שמאחסן את הסיומת של הנתיב של הבקשה. אם הנתיב הבסיסי של הבקשה הנכנסת היא /animals, והבקשה היא /animals/cat, ואז הערך של הפרמטר סיומת הנתיב היא המחרוזת המילולית "/cat".

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

שאלה: איזו סיומת של נתיב של שרת proxy תגרום להפעלה של somePolicy? בדיוק כמו בעזרת האופרטור Matches, יש רק אפשרות אחת במקרה הזה.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות פועלת? כן, כי הסיומת של נתיב שרת ה-proxy תואמת בדיוק ל-/cat. הפעולה לא תופעל אם הסיומת היא /bat או /dog או משהו כזה אחר.

עכשיו נוצר ביטוי רגולרי באמצעות המכפיל '*'. המספר הזה תואם לאפס תווים או יותר מהתו הקודם.

<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות מופעלת? לא! הסימן "*" תואם לאפס או יותר התו הקודם, שהוא "c".

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/ccccct

האם המדיניות פועלת? כן, כי התו הכללי לחיפוש תואם לאפס או יותר מהערך הקודם .

בשלב הבא אנחנו משתמשים במכמת ?, שמתאים לתו הקודם פעם אחת, או בכלל לא.

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות מופעלת? כן. המכמת ? תואם לאפס או לאירוע אחד של התו הקודם, שהוא a.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/ct

האם המדיניות פועלת? כן. ה'?' כמת מתאים לאחד או ללא מהתו הקודם. במקרה הזה, אין , כך התנאי מקבל את הערך True.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/caat

האם המדיניות פועלת? לא. המכפיל '?' תואם לאחד מהתווים הקודמים, שהוא a.

בשלב הבא, אנחנו משתמשים בסגנון '[abc]' או 'grouping' של ביטוי רגולרי. הוא תואם לתווים a,‏ b או c.

<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות מופעלת? כן. אנחנו משתמשים כאן בביטויים רגולריים, [cbr] תואם ל-c, ל-b או ל-r. גם השיחות הבאות נחשבות להתאמות:

GET http://artomatic-test.apigee.net/matchtest/bat

GET http://artomatic-test.apigee.net/matchtest/rat

אבל זו לא התאמה:

GET http://artomatic-test.apigee.net/matchtest/mat

שאלה: האם האופרטור JavaRegex תלוי אותיות רישיות?

כן. נניח שיש לכם תנאי כזה:

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat

האם המדיניות פועלת? כן, הביטוי הרגולרי תואם לאפס או לאחד מהתו הקודם, הוא "a".

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cAt

שאלה: האם המדיניות מופעלת?

לא, מכיוון שהאות A גדולה לא תואם לאותיות קטנות "a".

MatchesPath

אפשר לציין גם את האופרטור MatchesPath כך: "~/". הוא נראה קצת כמו Matches (~) והאופרטורים של JavaRegex (~~). אבל MatchesPath שונה לגמרי.

חשוב לזכור שהאופרטור הזה מתייחס לנתיב כסדרה של חלקים. לכן, אם הנתיב הוא /animals/cats/wild, אפשר לחשוב עליו כעל נתיב שמורכב מהחלקים /animals,‏ /cats ו-/wild.

האופרטור MatchesPath מאפשר להשתמש בשני תווים כלליים לחיפוש: כוכבית אחת (*) ו כוכבית כפולה (**). הכוכבית הבודדת תואמת לרכיב נתיב אחד. הכוכבית הכפולה תואמת רכיב נתיב אחד או יותר.

נתבונן בדוגמה. בדוגמה הזו אנחנו בודקים את המשתנה proxy.pathsuffix, שהוא משתנה מובנה ב-Edge שמאחסן את הסיומת של הנתיב של הבקשה. אבל כדאי לשים לב: לבדוק את הערך של כל משתנה זרימה שמכיל מחרוזת.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

שאלה: איזה סיומת של נתיב שרת proxy תגרום להפעלה של SomePolicy?

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals

שאלה: האם המדיניות מופעלת?

לא, כי התנאי מחייב רכיב נתיב נוסף אחרי "/animals", כפי שצוין על ידי "/*".

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals/

האם המדיניות פועלת? כן, הנתיב כולל רכיב נתיב נוסף (החלק שאחרי "/animals/"), אבל הוא פשוט ריק.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

האם המדיניות מופעלת? כן, כי הנתיב כולל בבירור רכיב ("/cats") שמופיע אחרי "/animals"

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

שאלה: האם המדיניות מופעלת?

לא, כי הכוכבית היחידה תואמת רק לרכיב נתיב אחד, ו-API הזה מכיל יותר מרכיב אחד אחרי '/animals'.

עכשיו נשתמש בכוכבית הכפולה:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

שאלה: איזה סיומת של נתיב שרת proxy תגרום להפעלה של SomePolicy?

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals

האם המדיניות מופעלת? לא, כי התנאי מחייב לפחות רכיב נתיב אחד מהרכיבים הבאים שצוינו על ידי '/**'.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals/

האם המדיניות פועלת?

כן, בנתיב יש רכיב נתיב נוסף (החלק אחרי /animals/), אבל הוא פשוט ריק.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

האם המדיניות מופעלת?

כן, כי בנתיב יש לפחות רכיב אחד שמגיע אחרי /animals

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

האם המדיניות פועלת?

כן, כי בנתיב יש יותר מרכיב אחד שמגיע אחרי /animals

שילוב של כוכבים

אפשר להשתמש בשילובים של כוכבית אחת (*) וכוכבית כפולה (**) כדי לשפר את ההתאמה של הנתיב.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

קריאה ל-API:

כל הקריאות האלה ל-API יגרמו להתאמה:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/

וגם

GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian

וגם

GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches

משאבי API

שירותים מבוססי-REST הם אוספים של משאבי API. משאב API הוא קטע של נתיב URI שמזהה ישות כלשהי, שמפתחים יכולים לגשת אליה על ידי קריאה ל-API שלכם. לדוגמה, אם השירות שלכם מספק דוחות מזג אוויר ותחזיות מזג אוויר, יכול להיות ששירות הקצה העורפי שלכם יגדר שני משאבי API:

  • http://mygreatweatherforecast.com/reports
  • http://mygreatweatherforecast.com/forecasts

כשיוצרים שרת proxy ל-API (כפי שמתואר במאמר יצירת שרת ה-proxy הראשון ל-API), יוצרים לפחות כתובת URL בסיסית חלופית שממופה לשירות הקצה העורפי. לדוגמה:

כתובת URL בסיסית לקצה העורפי כתובת URL חדשה או שווה ערך של שרת proxy ל-API
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

בשלב הזה אפשר לבצע קריאות ל-API לקצה העורפי באמצעות כל אחת מכתובות ה-URL הבסיסיות. אבל כשמשתמשים את כתובת האתר של ה-Proxy ל-API, דברים מתחילים להיות מעניינים.

בנוסף לניתוח הנתונים של ה-API ש-Edge מתחיל לאסוף כשמשתמשים בשרת ה-proxy ל-API, שרתי proxy מאפשרים גם להגדיר תהליכים מותנים שממופים למשאבים בקצה העורפי. בעיקרון, "אם קריאה ל-GET מגיעה אל המשאב /reports, Edge צריך לעשות משהו."

בתמונה הבאה מוצג ההבדל בהתנהגות בין שתי כתובות URL שבסופו של דבר ניגשות לאותו קצה עורפי. אחת היא כתובת ה-URL של המשאב ללא שרת proxy, והשנייה היא שרת proxy של Edge API עם תהליך מותנה לאותו משאב לקצה העורפי. נתאר בפירוט רב יותר את התהליכים המותנים שלמטה.

איך שרתי proxy ל-API ממפים למשאבים ספציפיים בקצה העורפי

באמצעות כתובת URL של שרת proxy ל-API שממופה לכתובת ה-URL הבסיסית של שירות הקצה העורפי (כשיוצרים את שרת proxy), אפשר להוסיף תהליכים מותנים למשאבים ספציפיים, כמו /reports וגם /forecasts מקורות מידע שהוזכרו קודם לכן.

נניח שרציתם לבקש מ-Edge " לעשות משהו" כששיחות מגיעות /reports או /forecasts משאבים. בשלב הזה לא אומרים ל-Edge מה לעשות, רק שהוא צריך להקשיב לשיחות למשאבים האלה. עושים את זה עם תנאים. בשרת ה-proxy של Edge API אפשר ליצור תהליכים מותנים עבור /reports ו-/forecasts. למטרות רעיוניות, ה-API הבא ה-XML של שרת ה-proxy מראה איך התנאים האלה עשויים להיראות.

<Flows>
    <Flow name="reports">
        <Description/>
        <Request/>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition>
    </Flow>
    <Flow name="forecasts">
        <Description/>
        <Request/>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/forecasts") and (request.verb = "GET")</Condition>
    </Flow>
</Flows>

התנאים האלה אומרים, "כשבקשת GET מגיעה עם /reports /forecasts בכתובת ה-URL, דפדפן Edge יעשה את כל מה שאתם (מפתח ה-API) יגדירו לו. באמצעות המדיניות שאתם מצרפים לתהליכי העבודה האלה.

הנה דוגמה לכך שאפשר לומר ל-Edge מה לעשות כשתנאי מסוים מתקיים. ב-XML של שרת ה-proxy של ה-API הבא, כשנשלחת בקשת GET אל https://yourorg-test.apigee.net/mygreatweatherforecast/reports,‏ Edge מבצע את המדיניות 'XML-to-JSON-1' בתגובה.

<Flows>
    <Flow name="reports">
        <Description/>
        <Request/>
        <Response>
            <Step>
                <Name>XML-to-JSON-1</Name>
            </Step>
        </Response>
        <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition>
</Flow>

בנוסף לתהליכים התנאייים האופציונליים האלה, לכל שרת proxy של API יש גם שני תהליכים שמוגדרים כברירת מחדל: <PreFlow> שמופעל לפני התהליכים התנאייים, ו-<PostFlow> שמופעל אחרי התהליכים התנאייים. הם שימושיים לביצוע מדיניות כשמתבצעת כל קריאה לשרת proxy של API. לדוגמה, אם רוצים לאמת את מפתח ה-API של האפליקציה בכל קריאה, ללא קשר למשאב הקצה העורפי שאליו מתבצעת הגישה, אפשר להגדיר מדיניות אימות מפתח API ב-<PreFlow>. מידע נוסף על תהליכים זמין במאמר הגדרת תהליכים.

יצירת תהליכים מותנים למשאבים בקצה העורפי

הגדרת תהליכים מותנים למשאבים בקצה העורפי בשרת proxy ל-API היא אופציונלית לחלוטין. עם זאת, התהליכים המותנים האלה נותנים לכם את היכולת להחיל ניהול פרטני מעקב.

בפורטל תוכלו:

  • להחיל ניהול באופן שמשקף את הסמנטיקה של מודל ה-API
  • החלת מדיניות והתנהגות לפי סקריפט על נתיבים ספציפיים של משאבים (URI)
  • איסוף מדדים פרטניים לשירותי Analytics

לדוגמה, נניח שאתם צריכים להחיל סוגים שונים של לוגיקה על המשאבים /developers ו-/apps בקצה העורפי.

כדי לעשות זאת, צריך להוסיף שני תהליכי עבודה מותנים בשרת ה-proxy ל-API: /developers ו /apps.

בתצוגה 'פיתוח' של החלונית 'ניווט' בעורך proxy ל-API, לוחצים על הסמל +. שמופיע כברירת מחדל בנקודות הקצה של שרת ה-proxy.

בחלון New Conditional Flow (תהליך מותנה חדש), מזינים את הגדרות המפתחות הבאות:

  • שם התהליך: מפתחים
  • Condition Type: Path
  • נתיב: /developers

התנאי יופעל (והמדיניות תתבצע) אם תישלח קריאה לשרת ה-proxy עם /developers בסוף ה-URI.

עכשיו מוסיפים תהליך מותנה של /apps, ונניח שרוצים שהתנאי יופעל גם URI וגם את פועל POST בבקשה. ההגדרה כוללת הגדרה של הבאים:

  • Flow Name: אפליקציות
  • Condition Type: נתיב ופועל
  • Path: /apps
  • פועל: POST

התנאי יופעל (והמדיניות תתבצע) אם תישלח קריאה לשרת ה-proxy עם /apps בסוף ה-URI ופועל POST.

בחלונית Navigator יופיעו תהליכים חדשים לאפליקציות מפתחים.

צריך לבחור את אחד התהליכים כדי להציג את ההגדרה של התהליך המותנה בעורך ה-proxy ל-API תצוגת קוד:

<Flow name="Apps">
    <Description>Developer apps registered in Developer Services</Description>
    <Request/>
    <Response/>
    <Condition>(proxy.pathsuffix MatchesPath "/apps") and (request.verb = "POST")</Condition>
</Flow>

כמו שאפשר לראות, משאבי API הם פשוט תהליכים מותנים שמעריכים את נתיב ה-URI של של בקשה לנתונים נכנסים. (המשתנה proxy.pathsuffix מזהה את ה-URI של הבקשה הבאה BasePath שהוגדר בתצורה של ProxyEndpoint.)

כל משאב API שאתם מגדירים מוטמע באמצעות תהליך מותנה ב-API proxy. (ראו הגדרת תהליכי עבודה).

לאחר פריסת ה-proxy ל-API בסביבת הבדיקה, הבקשה הבאה:

http://{org_name}-test.apigee.net/{proxy_path}/apps

התנאי יהיה נכון, והתהליך הזה, יחד עם כל כללי המדיניות המשויכים, יבוצע.

התנאי הבא בדוגמה הבאה משתמש בביטוי רגולרי של Java כדי לזהות קריאות שבוצעו אל משאב אחד (/apps), עם או בלי קו נטוי בסוף (/apps או) /apps/**):

<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>

למידע נוסף על סוג התנאי הזה, ראו איך להתאים ללא קשר ... בקהילת Apigee.

בניית מודלים של מזהי URI היררכיים

בחלק מהמקרים יהיו לכם משאבי API היררכיים. לדוגמה, השירותים למפתחים ב-API מוצגת שיטה להצגת כל האפליקציות ששייכות למפתח. נתיב ה-URI הוא:

/developers/{developer_email}/apps

יכול להיות שיש לכם משאבים שבהם נוצר מזהה ייחודי לכל ישות באוסף. לפעמים מוסיפים הערות באופן הבא:

/genus/:id/species

הנתיב הזה חל באופן שווה על שני מזהי ה-URI הבאים:

/genus/18904/species
/genus/17908/species

כדי לייצג את המבנה הזה במשאב API, אפשר להשתמש בתווים כלליים לחיפוש. לדוגמה:

/developers/*/apps
/developers/*example.com/apps
/genus/*/species

תפתור כראוי את מזהי ה-URI ההיררכיים כמשאבי API.

במקרים מסוימים, במיוחד עבור ממשקי API בהיררכיה עמוקה, ייתכן שתרצו פשוט לפתור את כל מה שבר מסוים של ה-URI. כדי לעשות זאת, צריך להשתמש בתו כללי לחיפוש כפול של כוכבית בהגדרת המשאב. לדוגמה, אם מגדירים את משאב ה-API הבא:
/developers/**

משאב ה-API הזה יפתור את נתיבי ה-URI הבאים:

/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keys

כך נראה תנאי התהליך המותנה בהגדרת שרת ה-proxy ל-API:

<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>

דוגמאות נוספות

התנאי מצורף ל-RouteRule

<RouteRule name="default">
 <!--this routing executes if the header indicates that this is an XML call. If true, the call is routed to the endpoint XMLTargetEndpoint-->
  <Condition>request.header.content-type = "text/xml"</Condition>
  <TargetEndpoint>XmlTargetEndpoint</TargetEndpoint>
</RouteRule>

תנאי שמצורף למדיניות

<Step>
<!--the policy MaintenancePolicy only executes if the response status code is exactly 503-->
  <Condition>response.status.code = 503</Condition>
  <Name>MaintenancePolicy</Name>
</Step>

זרימה מותנית

<!-- this entire flow is executed only if the request verb is a GET-->
<Flow name="GetRequests">
  <Condition>request.verb="GET"</Condition>
  <Request>
    <Step>
<!-- this policy only executes if request path includes a term like statues-->
<Condition>request.path ~ "/statuses/**"</Condition>
      <Name>StatusesRequestPolicy</Name>
    </Step>
  </Request>
  <Response>
    <Step>
<!-- this condition has multiple expressions. The policy executes if the response code status is exactly 503 or 400-->
<Condition>(response.status.code = 503) or (response.status.code = 400)</Condition>
      <Name>MaintenancePolicy</Name>
    </Step>
  </Response>
</Flow>

אופרטורים לדוגמה בתנאים

הנה כמה דוגמאות לאופרטורים שמשמשים ליצירת תנאים:

  • request.header.content-type = "text/xml"
  • request.header.content-length < 4096 && request.verb = "PUT"
  • response.status.code = 404 || response.status.code = 500
  • request.uri MatchesPath "/*/statuses/**"
  • request.queryparam.q0 NotEquals 10

דוגמה מעשית: התעלמות מ-'/' בסוף נתיב

מפתחים של Edge בדרך כלל רוצים לטפל בשני הסיומת האלה של הנתיב: /cat ו-/cat/. הסיבה לכך היא שחלק מהמשתמשים או הלקוחות עשויים להפעיל את ה-API עם קו נטוי נוסף בסוף הנתיב, וצריך להיות לכם אפשרות לטפל בכך בהצהרות התנאי. תרחיש לדוגמה מדויק זה נדון בקהילת Apigee.

אם אתם מעדיפים, תוכלו לעשות זאת בלי להשתמש בביטוי רגולרי (regex): באופן הבא:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>((proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

זו אפשרות טובה. היא ברורה וקריאה.

אפשר לעשות את אותו הדבר באמצעות ביטוי רגולרי (regex), באופן הבא. הסוגריים משמשים לקיבוץ של החלק של ביטוי ה-regex במשפט, אבל הם לא חובה.

<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>

קריאות ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat
or

GET http://artomatic-test.apigee.net/matchtest/cat/

האם המדיניות פועלת? כן. שימו לב שבביטוי רגולרי, התו ? מציין התאמה לאפס תווים או לתו אחד מהתו הקודם. לכן, גם "/cat" וגם "/cat/" הם התאמות.

קריאה ל-API:

GET http://artomatic-test.apigee.net/matchtest/cat/spotted

האם המדיניות מופעלת? לא. הביטוי הרגולרי תואם לאפס או לאירוע אחד בלבד של את התו הקודם, ושום דבר אחר אסור.

התאמת מחרוזות שרירותיות באמצעות JavaRegex

בכל הדוגמאות בנושא הזה נסביר איך להתאים לאחד משתני התהליך המובנים: proxy.pathsuffix. חשוב לדעת שאפשר לבצע התאמה לתבנית בכל מחרוזת שרירותית או במשתנה תהליך, גם אם מדובר במשתנה תהליך מובנה כמו proxy.pathsuffix.

לדוגמה, אם יש תנאי שבודק מחרוזת שרירותית, אולי תוחזר מחרוזת. במטען ייעודי (payload) של קצה עורפי, או במחרוזת שמוחזרת מחיפוש של שרת אימות, אפשר להשתמש שתואמים לאופרטורים כדי לבדוק אותו. אם משתמשים ב-JavaRegex, הביטוי הרגולרי ישווה לכל מחרוזת הנושא. אם הנושא הוא 'abc' והביטוי הרגולרי הוא '‎[a-z]‎', לא תהיה התאמה כי הביטוי '‎[a-z]‎' תואם בדיוק לאות אחת. ביטוי '[a-z]+' עובדת, וגם [a-z]* וגם [a-z]{3}.

נבחן דוגמה קונקרטית. נניח ששרת האימות מחזיר רשימה של תפקידים כמחרוזת מופרדת בפסיקים: "editor, author, guest".

כדי לבדוק את הנוכחות של תפקיד העורך, המבנה הזה לא יפעל כי 'עריכה' תואם לערך רק חלק מהמחרוזת כולה.

<Condition>returned_roles ~~ "editor"</Condition>

עם זאת, המבנה הזה יפעל:

<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>

התכונה פועלת כי היא מביאה בחשבון מעברי מילים וכל חלק אחר של המחרוזת עם תחילית וסיומת .*

בדוגמה הזו, אפשר גם לבדוק אם יש 'עריכה' באמצעות האופרטור Matches:

<Condition>returned_roles ~~ "*editor*")</Condition>

עם זאת, במקרים שבהם נדרש דיוק רב יותר, מומלץ בדרך כלל להשתמש ב-JavaRegex.

בריחה ממרכאות כפולות בביטויים של JavaRegex

התחביר של התנאי דורש שביטוי JavaRegex יהיה מוקף במירכאות כפולות; ולכן אם יש לך ביטוי רגולרי שכולל מירכאות כפולות, צריך דרך חלופית להתאים להם. התשובה היא Unicode. לדוגמה, נניח ששלחתם כותרת שכוללת סוגריים כפולים, כמו זו:
 -H 'content-type:multipart/related; type="application/xop+xml"'
אם תנסו להתאים את הכותרת הזו לתנאי של ביטוי רגולרי, תופיע הודעת השגיאה 'תנאי לא חוקי' כי הביטוי כולל את הסוגרים הכפולים:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
הפתרון הוא להחליף את הסוגרים הכפולים שמבוססים על ASCII ב-Unicode המקביל שלהם, \u0022. לדוגמה, הביטוי הבא תקין ונותן את התוצאה הצפויה:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"