אתם צופים במסמכי התיעוד של Apigee Edge.
כדאי לעיין במסמכי התיעוד של Apigee X. מידע
משפטי תנאי הם מבנה בקרה נפוץ בכל שפות התכנות. בדומה לשפת תכנות, הגדרת שרת proxy ל-API תומכת במשפטי תנאי ל-Flows, ל-Policies, ל-Steps ול-RouteRules. הגדרתם התנהגות דינמית ל-API באמצעות הגדרת משפטי תנאי. ההתנהגות הדינמית הזו מאפשרת לכם לבצע פעולות כמו המרת XML ל-JSON רק למכשירים ניידים, או ניתוב לכתובת URL של קצה עורפי על סמך סוג התוכן או פועל ה-HTTP של הודעת הבקשה.
במאמר הזה מוסבר איך להשתמש בתנאים כדי להחיל באופן דינמי תכונות של ניהול API בזמן ריצה, בלי לכתוב קוד.
הגדרת משפטי תנאי
התנהגות מותנית מיושמת בשרתי proxy של API באמצעות שילוב של תנאים ומשתנים. משפט מותנה נוצר באמצעות רכיב Condition. התנאי הבא הוא תנאי ריק:
<Condition></Condition>
כדי ליצור משפט מותנה, מוסיפים אופרטור מותנה ומשתנה כדי ליצור את המבנה הבא:
<Condition>{variable.name}{operator}{"value"}</Condition>
אופרטורים מותנים נתמכים כוללים = (שווה), != (לא שווה) ו-> (גדול מ-). כדי שהקוד יהיה קריא יותר, אפשר גם לכתוב את התנאים כך:
text: equals, notequals, greaterthan.
כשעובדים עם נתיבי URI, אפשר להשתמש ב-~/ או ב-MatchesPath. אפשר גם להתאים ביטויים רגולריים של JavaRegex באמצעות האופרטור ~~.
התנאים משמשים להגדרת זרימות מותנות של שרתי proxy ל-API למשאבי API בקצה העורפי, כפי שמתואר במאמר יצירת זרימות מותנות למשאבי API בקצה העורפי. רשימה מלאה של תנאים מופיעה במאמר חומר עזר בנושא תנאים.
משתנים
התנאים פועלים על ידי הערכת הערכים של משתנים. משתנה הוא מאפיין של טרנזקציית HTTP שמופעלת על ידי proxy ל-API, או מאפיין של הגדרת proxy ל-API. בכל פעם שמתקבלת בקשה מ-proxy ל-API מאפליקציה, Apigee Edge מאכלס רשימה ארוכה של משתנים שמשויכים לדברים כמו זמן המערכת, מידע הרשת של האפליקציה, כותרות HTTP בהודעות, הגדרת proxy ל-API, הרצת מדיניות וכן הלאה. כך נוצר הקשר העשיר שבו אפשר להשתמש כדי להגדיר משפטי תנאי.
משתנים תמיד משתמשים בסימון נקודות. לדוגמה, כותרות HTTP בהודעת הבקשה זמינות כמשתנים שנקראים request.header.{header_name}. לכן, כדי להעריך את כותרת Content-type, אפשר להשתמש במשתנה 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.
כדי להפעיל התנהגות דינמית, אפשר לצרף תנאים לזרימות, לשלבים ולכללי ניתוב.
כשמצרפים תנאי ל-Flow, יוצרים 'Flow מותנה'. תהליכים מותנים פועלים רק כשהתנאי הוא true. אפשר לצרף כמה מדיניות שרוצים ל-Flow מותנה. בעזרת Flow מותנה, אתם יכולים ליצור כללי עיבוד מיוחדים מאוד להודעות בקשה או תגובה שעומדות בקריטריונים מסוימים.
לדוגמה, כדי ליצור Flow שמופעל רק כשפועל הפועל של הבקשה הוא GET:
<Flows> <Flow name="ExecuteForGETs"> <Condition>request.verb="GET"</Condition> </Flow> </Flows>
כדי ליצור Flow אחד לבקשות GET ו-Flow אחר לבקשות 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.
אם התנאי מחזיר את הערך true, כלומר הערך של המשתנה request.header.User-Agent שווה ל-Mozilla, מתבצעת ההפעלה של Flow מותנה, והמדיניות 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 Flow באופן הבא.
<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: התאמת תבניות פשוטה
- אופרטור JavaRegex: שליטה מדויקת יותר בהתאמה
- האופרטור MatchesPath: התאמה של קטע נתיב
התאמות
נתחיל עם אופרטור ההתניה Matches (תואם) או ~. שני האופרטורים האלה זהים – הגרסה האנגלית, Matches, נחשבת לאפשרות קריאה יותר.
סיכום: האופרטור 'תואם' מאפשר לכם לבחור בין שתי אפשרויות. אפשר להתאים את המחרוזת באופן מילולי, או לבצע התאמה באמצעות התו הכללי '*'. כמו שאפשר לצפות, התו הכללי מתאים לאפס תווים או יותר. בואו נראה איך זה עובד.
בדוגמת ה-XML הבאה מוצג תנאי לביצוע השלב. היא מפעילה את המדיניות SomePolicy כשהתנאי
מחזיר את הערך true. בדוגמה הזו, אנחנו בודקים את המשתנה proxy.pathsuffix, משתנה מובנה ב-Edge שמאחסן את הסיומת של נתיב כתובת ה-URL של הבקשה. עם זאת, אפשר לבדוק את הערך של כל משתנה זרימה שמכיל מחרוזת. לכן, במקרה הזה, אם נתיב הבסיס של הבקשה הנכנסת הוא /animals והבקשה היא /animals/cat, אז סיומת הנתיב היא המחרוזת המילולית /cat.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix Matches "/cat")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>שאלה: איזה הסיומת של נתיב כתובת ה-URL של שרת proxy תגרום להרצה של SomePolicy? יש רק אפשרות אחת.
קריאה ל-API:
GET http://artomatic-test.apigee.net/matchtest/cat
האם המדיניות מופעלת? כן, כי הסיומת של נתיב כתובת ה-URL של ה-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" יוצרת התאמה. שימו לב איך ביטוי כזה יכול להכניס אתכם לצרות כי הוא מתאים לכל מה שאחרי התווים המילוליים.
שאלה: האם האופרטור Matches (תואם) הוא תלוי אותיות רישיות?
כן. נניח שיש לכם תנאי כזה:
<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
האם המדיניות מופעלת? כן, יש התאמה בין האותיות הרישיות.
שאלה: איך משתמשים באופרטור Matches כדי לבטל את המשמעות של תווים?
כדי לבטל את המשמעות של תווים שמורים, משתמשים בתו האחוז "%". לדוגמה:
<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
כפי שאפשר לראות, האופרטור Matches מתאים מאוד למצבים פשוטים. אבל אפשר להשתמש באופרטור אחר, JavaRegex או ~~. שני האופרטורים האלה זהים, אבל JavaRegex נחשב לקריא יותר. הוא נקרא JavaRegex כי הוא מאפשר התאמה של דפוסי ביטויים רגולריים, ו-Edge פועל לפי אותם כללים כמו המחלקות בחבילה java.util.regex בשפת Java. האופן שבו האופרטור JavaRegex פועל שונה מאוד מהאופרטור Matches, ולכן חשוב לא להתבלבל בין השניים.
סיכום: האופרטור JavaRegex מאפשר להשתמש בתחביר של ביטויים רגולריים במשפטי התניה.
הקוד הבא מציג תנאי לביצוע השלב. היא מפעילה את המדיניות SomePolicy אם התנאי
מחזיר את הערך True. בדוגמה הזו, אנחנו בודקים את המשתנה proxy.pathsuffix, משתנה מובנה ב-Edge שמאחסן את הסיומת של נתיב כתובת ה-URL של הבקשה. אם נתיב הבסיס של הבקשה הנכנסת הוא /animals והבקשה היא /animals/cat, אז הסיומת של נתיב כתובת ה-URL היא המחרוזת המילולית /cat.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>שאלה: איזה הסיומת של נתיב כתובת ה-URL של שרת proxy תגרום להרצה של SomePolicy? בדומה לאופרטור Matches, במקרה הזה יש רק אפשרות אחת.
קריאה ל-API:
GET http://artomatic-test.apigee.net/matchtest/cat
האם המדיניות מופעלת? כן, כי הסיומת של נתיב כתובת ה-URL של ה-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
האם המדיניות מופעלת? כן. הכמת ? תואם למופע אחד של התו הקודם או לאף מופע. במקרה הזה, אין תו 'a', ולכן התנאי מחזיר True.
קריאה ל-API:
GET http://artomatic-test.apigee.net/matchtest/caat
האם המדיניות מופעלת? לא. הכמותן '?' תואם לאחד מהתווים הקודמים, שהוא 'a'.
לאחר מכן, נשתמש בסגנון הביטוי הרגולרי '[abc]' או 'קיבוץ'. הוא תואם לתווים "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 שמאחסן את הסיומת של נתיב כתובת ה-URL של הבקשה. עם זאת, אפשר לבדוק את הערך של כל משתנה זרימה שמכיל מחרוזת.
<PreFlow name="PreFlow">
<Request>
<Step>
<Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
<Name>SomePolicy</Name>
</Step>
</Request>
<Response/>
</PreFlow>שאלה: איזה הסיומת של נתיב כתובת ה-URL של שרת 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>שאלה: איזה הסיומת של נתיב כתובת ה-URL של שרת 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
שירותי RESTful הם אוספים של משאבי API. משאב API הוא קטע של נתיב URI שמזהה ישות מסוימת שמפתחים יכולים לגשת אליה באמצעות קריאה ל-API שלכם. לדוגמה, אם השירות שלכם מספק דוחות ותחזיות של מזג האוויר, יכול להיות שהשירות לקצה העורפי יגדיר שני משאבי API:
- http://mygreatweatherforecast.com/reports
- http://mygreatweatherforecast.com/forecasts
כשיוצרים proxy ל-API (כפי שמוסבר במאמר פיתוח פתרונות API proxy ראשון), יוצרים לפחות כתובת URL בסיסית של אימייל חלופי שממופה לשירות לקצה העורפי. לדוגמה:
| כתובת URL בסיסית של ה-Backend | כתובת 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 ל-API של Edge עם זרימה מותנית לאותו משאב בקצה העורפי. בהמשך נסביר על זרימות מותנות בפירוט רב יותר.

איך שרתי proxy ל-API ממופים למשאבים ספציפיים בקצה העורפי
אם כתובת ה-URL של proxy ל-API ממופה לכתובת הבסיסית של שירות לקצה העורפי (כשיוצרים את ה-proxy), אפשר להוסיף זרימות מותנות למשאבים ספציפיים, כמו המשאבים /reports ו-/forecasts שצוינו קודם.
נניח שאתם רוצים ש-Edge "יעשה משהו" כשמתקבלות שיחות למשאבי /reports או /forecasts. בשלב הזה אתם לא אומרים ל-Edge מה לעשות, אלא רק שהוא צריך להאזין לקריאות למשאבים האלה. הפעולה הזו מתבצעת באמצעות תנאים. ב-proxy ל-API של Edge, אפשר ליצור זרימות מותנות עבור /reports ו-/forecasts. לצורך המחשה, בדוגמה הבאה של XML של שרת proxy ל-API מוצג איך התנאים האלה יכולים להיראות.
<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
לדוגמה, נניח שאתם צריכים להחיל סוגים שונים של לוגיקה על משאבי ה-backend שלכם /developers ו-/apps.
כדי לעשות זאת, מוסיפים שני זרמי נתונים מותנים ב-proxy ל-API: /developers ו-/apps.
בתצוגה Develop (פיתוח) בחלונית Navigator (ניווט) של הכלי לעריכת proxy ל-API, לוחצים על סמל הפלוס לצד default (ברירת מחדל) ב-Proxy Endpoints (נקודות קצה של שרתי proxy).
![]()
בחלון 'זרימה מותנית חדשה', מזינים את הגדרות המפתח הבאות:
- שם רצף הפעולות: מפתחים
- Condition Type: Path
- נתיב: /developers

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

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

בוחרים באחד מהזרימות כדי לראות את הגדרת הזרימה המותנית בתצוגת הקוד של כלי העריכה של ה-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 שאתם מגדירים מיושם על ידי Flow מותנה ב-proxy ל-API. (ראו הגדרת תהליכי עבודה).
אחרי שפורסים את ה-proxy ל-API בסביבת הבדיקה, הבקשה הבאה:
http://{org_name}-test.apigee.net/{proxy_path}/appsיגרום להערכת התנאי כ-True, והזרימה הזו, יחד עם כל המדיניות המשויכת, תופעל.
תנאי הדוגמה הבא משתמש בביטוי רגולרי של Java כדי לזהות קריאות שבוצעו למשאב /apps עם או בלי קו נטוי בסוף (/apps או /apps/**):
<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>
מידע נוסף על סוג התנאי הזה זמין במאמר How to match regardless ... בקהילת Apigee.
בניית מודלים של כתובות URI היררכיות
במקרים מסוימים, משאבי ה-API יהיו היררכיים. לדוגמה, Developer Services 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
יבצע התאמת נתונים (resolve) של כתובות ה-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 = 500request.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, באופן הבא. הסוגריים משמשים לקיבוץ החלק של הביטוי הרגולרי בהצהרה, אבל הם לא חובה.
<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.
כדי לבדוק אם יש הרשאת עריכה, המבנה הזה לא יעבוד כי editor הוא רק חלק מהמחרוזת כולה.
<Condition>returned_roles ~~ "editor"</Condition>
אבל אפשר להשתמש במבנה הזה:
<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>
היא פועלת כי היא לוקחת בחשבון את ההפסקות בין המילים ואת כל החלקים האחרים של המחרוזת עם התחילית והסיומת .* .
בדוגמה הזו, אפשר גם לבדוק אם יש התאמה ל'עורך' באמצעות האופרטור Matches:
<Condition>returned_roles ~~ "*editor*")</Condition>
עם זאת, במקרים שבהם נדרש דיוק רב יותר, JavaRegex היא לרוב בחירה טובה יותר.
שימוש בתו בריחה למרכאות כפולות בביטויי JavaRegex
התחביר של התנאי מחייב להוסיף מירכאות כפולות לביטוי JavaRegex. לכן, אם יש לכם ביטוי Regex שכולל מירכאות כפולות, אתם צריכים דרך חלופית להתאמה שלהן. התשובה היא Unicode. לדוגמה, נניח שמעבירים כותרת שכוללת מירכאות כפולות, כמו הכותרת הבאה:-H 'content-type:multipart/related; type="application/xop+xml"'
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
\u0022. לדוגמה, הביטוי הבא תקין ומפיק את התוצאה הצפויה:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"