شرایط با متغیرهای جریان

شما در حال مشاهده مستندات Apigee Edge هستید.
به مستندات Apigee X مراجعه کنید .
اطلاعات

دستورات شرطی یک ساختار کنترلی رایج در تمام زبان‌های برنامه‌نویسی هستند. پیکربندی پروکسی API مانند یک زبان برنامه‌نویسی از دستورات شرطی برای Flowها، Policyها، Stepها و RouteRules پشتیبانی می‌کند. با تعریف دستورات شرطی، شما رفتار پویایی را برای API خود تعریف می‌کنید. این رفتار پویا به شما امکان می‌دهد کارهایی مانند تبدیل XML به JSON فقط برای دستگاه‌های تلفن همراه یا مسیریابی به یک URL بک‌اند بر اساس نوع محتوا یا HTTP verb پیام درخواست را انجام دهید.

این مبحث به شما نشان می‌دهد که چگونه از شرط‌ها برای اعمال پویای ویژگی‌های مدیریت API در زمان اجرا، بدون نوشتن هیچ کدی، استفاده کنید.

پیکربندی دستورات شرطی

رفتار شرطی در پروکسی‌های API با استفاده از ترکیبی از شرط‌ها و متغیرها پیاده‌سازی می‌شود. یک عبارت شرطی با استفاده از یک عنصر Condition ایجاد می‌شود. در زیر یک شرط خالی آمده است:

<Condition></Condition>

برای ایجاد یک عبارت شرطی، یک عملگر شرطی و یک متغیر اضافه می‌کنید تا ساختار زیر ایجاد شود:

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

عملگرهای شرطی پشتیبانی‌شده شامل = (مساوی)، != (نامساوی) و > (بزرگتر از) هستند. برای خوانایی بیشتر، می‌توانید شرط‌ها را به صورت متنی نیز بنویسید: equals ، notequals ، greaterthan .

هنگام کار با مسیرهای URI می‌توانید از ~/ یا MatchesPath استفاده کنید. همچنین می‌توانید عبارات منظم JavaRegex را با عملگر ~~ مطابقت دهید.

شرط‌ها برای تعریف جریان‌های شرطی پروکسی API برای منابع API بک‌اند استفاده می‌شوند، که در بخش «ایجاد جریان‌های شرطی برای منابع API بک‌اند» توضیح داده شده است. برای فهرست کامل شرط‌ها، به مرجع شرط‌ها مراجعه کنید.

متغیرها

شرط‌ها کار خود را با ارزیابی مقادیر متغیرها انجام می‌دهند. یک متغیر، ویژگی یک تراکنش HTTP است که توسط یک پروکسی API اجرا می‌شود، یا ویژگی پیکربندی خود پروکسی API است. هر زمان که یک پروکسی API درخواستی از یک برنامه دریافت می‌کند، Apigee Edge لیست طولانی از متغیرهایی را که با مواردی مانند زمان سیستم، اطلاعات شبکه برنامه، هدرهای HTTP روی پیام‌ها، پیکربندی پروکسی 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 از چنین دستوری برای ارزیابی شرایط استفاده می‌کند. مثال بالا اگر فعل HTTP مرتبط با درخواست GET باشد، مقدار true را برمی‌گرداند. اگر فعل HTTP مرتبط با درخواست POST باشد، مقدار statement برابر با false ارزیابی می‌شود.

برای فعال کردن رفتار پویا، می‌توانید شرایط را به جریان‌ها، مراحل و قوانین مسیر (RouteRules) پیوست کنید.

وقتی شرطی را به یک جریان (Flow) اضافه می‌کنید، یک «جریان شرطی» (conditional flow) ایجاد می‌کنید. جریان‌های شرطی فقط زمانی اجرا می‌شوند که شرط درست (true) باشد. می‌توانید هر تعداد سیاست (Policy) که می‌خواهید را به یک جریان شرطی اضافه کنید. یک جریان شرطی شما را قادر می‌سازد تا قوانین پردازش بسیار تخصصی را برای پیام‌های درخواست یا پاسخ که معیارهای خاصی را برآورده می‌کنند، ایجاد کنید.

برای مثال، برای ایجاد یک Flow که فقط زمانی اجرا می‌شود که فعل درخواست 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>

پس از تعریف چنین جریان‌های شرطی، می‌توانید سیاست‌ها را به آنها پیوست کنید و به یک پروکسی API این امکان را بدهید که یک مجموعه از سیاست‌ها را برای درخواست‌های GET و مجموعه دیگری از سیاست‌ها را برای درخواست‌های POST اعمال کند.

برای اطلاعات جامع در مورد مرجع، به منابع زیر مراجعه کنید:

مثال ۱

مثال زیر یک جریان شرطی واحد به نام Convert-for-devices نشان می‌دهد که در جریان پاسخ ProxyEndpoint پیکربندی شده است. Condition را به عنوان یک عنصر به موجودیتی که شرط روی آن اعمال می‌شود اضافه کنید. در این مثال، condition یک جزء از جریان است. بنابراین، جریان هر زمان که عبارت به 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 را بررسی می‌کند تا ببیند آیا شرط درست است یا خیر.

اگر شرط درست باشد، یعنی مقدار متغیر request.header.User-Agent برابر با Mozilla باشد، آنگاه Flow شرطی اجرا می‌شود و سیاست XMLtoJSON به نام ConvertToJSON اعمال می‌شود. در غیر این صورت، Flow اجرا نمی‌شود و پاسخ XML بدون تغییر (در قالب XML) به برنامه درخواست‌کننده بازگردانده می‌شود.

مثال ۲

بیایید از یک مثال خاص استفاده کنیم که در آن شما نیاز دارید پیام پاسخ را از XML به JSON تبدیل کنید - اما فقط برای دستگاه‌های تلفن همراه. ابتدا، سیاستی ایجاد کنید که پاسخ با فرمت XML را از API Weather به JSON تبدیل کند:

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

پیکربندی خط‌مشی فوق به پروکسی 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 اضافه کنید.

جریان شرطی را آزمایش کنید

در این درخواست نمونه، هدر HTTP User-Agent روی Mozilla تنظیم شده است که باعث می‌شود عبارت شرطی به مقدار درست (true) ارزیابی شود و جریان شرطی Convert-for-devices اجرا شود.

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

یا برای چاپ زیبا در جایی که پایتون در دسترس است:

$ 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" یا "~" نگاهی بیندازیم. این دو عملگر یکسان هستند -- نسخه انگلیسی آن، "Matches"، گزینه خواناتری محسوب می‌شود.

خلاصه: عملگر "مطابقت" دو امکان به شما می‌دهد. یا رشته را به معنای واقعی کلمه تطبیق دهید، یا با "*" یک تطبیق wildcard انجام دهید. همانطور که انتظار دارید، wildcard با صفر یا چند کاراکتر مطابقت دارد. بیایید ببینیم این چگونه کار می‌کند.

XML زیر یک شرط Step را نشان می‌دهد. این شرط، سیاست 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>

سوال: چه پسوند مسیر پروکسی باعث اجرای SomePolicy می‌شود؟ فقط یک احتمال وجود دارد.

فراخوانی API:

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

آیا این سیاست اجرا می‌شود؟ بله، زیرا پسوند مسیر پروکسی دقیقاً با " /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 کاراکترها را 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

سوال: آیا این سیاست اجرا می‌شود؟

بله، این مسیر، اگرچه کمی غیرمعمول است، اما مطابقت دارد.

جاوا رگکس

همانطور که می‌بینید، عملگر "Matches" برای موقعیت‌های ساده عالی است. اما می‌توانید از عملگر دیگری به نام "JavaRegex" یا "~~" استفاده کنید. این دو عملگر یکسان هستند، با این تفاوت که JavaRegex خواناتر در نظر گرفته می‌شود. به آن JavaRegex می‌گویند زیرا امکان تطبیق الگوی عبارات منظم را فراهم می‌کند و Edge از همان قوانین کلاس‌های موجود در بسته java.util.regex در زبان جاوا پیروی می‌کند. نحوه کار عملگر JavaRegex با عملگر Matches بسیار متفاوت است، بنابراین مهم است که این دو را با هم اشتباه نگیرید!

خلاصه: عملگر "JavaRegex" به شما امکان می‌دهد از سینتکس عبارات منظم در عبارات شرطی استفاده کنید.

کد زیر یک شرط Step را نشان می‌دهد. اگر شرط درست باشد، سیاست SomePolicy را اجرا می‌کند. در این مثال، متغیر 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>

سوال: چه پسوند مسیر پروکسی باعث اجرای SomePolicy می‌شود؟ درست مانند عملگر Matches، در این مورد فقط یک احتمال وجود دارد.

فراخوانی API:

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

آیا این سیاست اجرا می‌شود؟ بله، زیرا پسوند مسیر پروکسی دقیقاً با " /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» وجود ندارد، بنابراین شرط به صورت درست ارزیابی می‌شود.

فراخوانی API:

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

آیا این سیاست اجرا می‌شود؟ خیر. کمیت‌سنج «؟» با یکی از کاراکترهای قبلی که « a » است، مطابقت دارد.

در مرحله بعد، از سبک « [abc] » یا «گروه‌بندی» در عبارت regex استفاده می‌کنیم. این سبک با کاراکترهای « 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 می‌توان به صورت "~/" نیز مشخص کرد. این عملگر کمی شبیه به عملگرهای Matches (~) و JavaRegex (~~) است. اما MatchesPath کاملاً متفاوت است.

فقط به یاد داشته باشید که این عملگر به یک مسیر به عنوان مجموعه‌ای از بخش‌ها نگاه می‌کند. بنابراین، اگر مسیر به صورت /animals/cats/wild باشد، می‌توانید مسیر را متشکل از بخش‌های " /animals "، " /cats " و " /wild " در نظر بگیرید.

عملگر MatchesPath به شما امکان می‌دهد از دو نمادگذاری wildcard استفاده کنید: یک ستاره تکی (*) و یک ستاره دوتایی (**). ستاره تکی با یک عنصر مسیر مطابقت دارد. ستاره دوتایی با یک یا چند عنصر مسیر مطابقت دارد.

بیایید به یک مثال نگاه کنیم. در این مثال، ما متغیر proxy.pathsuffix آزمایش می‌کنیم، یک متغیر داخلی در Edge که پسوند مسیر درخواست را ذخیره می‌کند. با این حال، توجه داشته باشید که می‌توانید مقدار هر متغیر جریانی که حاوی یک رشته است را آزمایش کنید.

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

سوال: چه پسوند مسیر پروکسی باعث اجرای 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>

سوال: چه پسوند مسیر پروکسی باعث اجرای 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 شما به آن دسترسی پیدا کنند. برای مثال، اگر سرویس شما گزارش‌های آب و هوا و پیش‌بینی‌های آب و هوا را ارائه می‌دهد، سرویس backend شما ممکن است دو منبع API تعریف کند:

  • http://mygreatweatherforecast.com /گزارش‌ها
  • http://mygreatweatherforecast.com /forecasts

وقتی یک پروکسی API ایجاد می‌کنید (همانطور که در بخش « اولین پروکسی API خود را بسازید » نشان داده شده است)، حداقل یک URL پایه مستعار ایجاد می‌کنید که به سرویس backend شما نگاشت می‌شود. برای مثال:

آدرس اینترنتی پایه بک‌اند آدرس پروکسی API جدید/معادل
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

در این مرحله می‌توانید با استفاده از هر دو URL پایه، فراخوانی‌های API را به backend خود انجام دهید. اما وقتی از URL پروکسی API استفاده می‌کنید، اوضاع جالب می‌شود.

علاوه بر تجزیه و تحلیل‌های API که Edge هنگام استفاده از پروکسی API شروع به جمع‌آوری آنها می‌کند، پروکسی‌ها به شما امکان می‌دهند جریان‌های شرطی را نیز تعریف کنید که به منابع موجود در backend شما نگاشت می‌شوند. در اصل، "اگر یک فراخوانی GET به منبع /reports وارد شود، Edge باید کاری انجام دهد."

تصویر زیر تفاوت رفتار بین دو URL را نشان می‌دهد که در نهایت به یک backend دسترسی دارند. یکی URL منبع بدون پروکسی و دیگری یک پروکسی Edge API با جریان شرطی به همان منبع backend است. جریان‌های شرطی را با جزئیات بیشتر در زیر شرح خواهیم داد.

چگونه پروکسی‌های API به منابع خاص backend نگاشت می‌شوند

با یک URL پروکسی API که به URL پایه سرویس backend (هنگام ایجاد پروکسی) نگاشت شده است، می‌توانید جریان‌های شرطی را به منابع خاص، مانند منابع /reports و /forecasts که قبلاً ذکر شد، اضافه کنید.

فرض کنید می‌خواهید وقتی فراخوانی‌ها به منابع /reports یا /forecasts می‌رسند، Edge «کاری انجام دهد». در این مرحله، شما به Edge نمی‌گویید که چه کاری انجام دهد، فقط باید به فراخوانی‌های مربوط به آن منابع گوش دهد. شما این کار را با شرط‌ها انجام می‌دهید. در پروکسی API Edge خود، می‌توانید جریان‌های شرطی برای /reports و /forecasts ایجاد کنید. برای اهداف مفهومی، پروکسی API XML زیر نشان می‌دهد که این شرط‌ها ممکن است چگونه باشند.

<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 آورده شده است. در API پروکسی XML زیر، وقتی یک درخواست 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>

علاوه بر این جریان‌های شرطی اختیاری، هر پروکسی API دارای دو جریان پیش‌فرض نیز هست: یک <PreFlow> که قبل از جریان‌های شرطی شما اجرا می‌شود و یک <PostFlow> که بعد از جریان‌های شرطی شما اجرا می‌شود. این دو جریان برای اجرای سیاست‌ها هنگام هرگونه فراخوانی به یک پروکسی API مفید هستند. به عنوان مثال، اگر می‌خواهید کلید API یک برنامه را با هر فراخوانی، صرف نظر از منبع backend که به آن دسترسی پیدا می‌شود، تأیید کنید، می‌توانید یک سیاست Verify API Key را روی <PreFlow> قرار دهید. برای اطلاعات بیشتر در مورد جریان‌ها، به پیکربندی جریان‌ها مراجعه کنید.

ایجاد جریان‌های شرطی برای منابع backend

تعریف جریان‌های شرطی برای منابع backend در یک پروکسی API کاملاً اختیاری است. با این حال، این جریان‌های شرطی به شما امکان اعمال مدیریت و نظارت دقیق را می‌دهند.

شما قادر خواهید بود:

  • مدیریت را به گونه‌ای اعمال کنید که منعکس کننده معنای مدل API شما باشد.
  • اعمال سیاست‌ها و رفتارهای اسکریپت‌شده به مسیرهای منابع (URI) منفرد
  • جمع‌آوری معیارهای دقیق برای سرویس‌های تحلیلی

برای مثال، تصور کنید که باید انواع مختلفی از منطق را در منابع backend /developers /apps خود اعمال کنید.

برای انجام این کار، دو جریان شرطی را در پروکسی API خود اضافه می‌کنید: /developers و /apps .

در نمای توسعه (Develop view) از پنل ناوبری ویرایشگر پروکسی API، روی آیکون + کنار default در Proxy Endpoints کلیک کنید.

در پنجره‌ی «جریان شرطی جدید»، پیکربندی‌های کلیدی زیر را وارد می‌کنید:

  • نام جریان : توسعه‌دهندگان
  • نوع وضعیت : مسیر
  • مسیر : /توسعه‌دهندگان

اگر فراخوانی به پروکسی با /developers در انتهای URI ارسال شود، این شرط فعال می‌شود (و سیاست‌ها اجرا می‌شوند).

حالا یک جریان شرطی برای /apps اضافه کنید و فرض کنید می‌خواهید شرط هم روی URI و هم روی POST در یک درخواست فعال شود. پیکربندی شامل تنظیم موارد زیر است:

  • نام جریان : برنامه‌ها
  • نوع شرط : مسیر و فعل
  • مسیر : /apps
  • فعل : پست کردن

اگر فراخوانی به پروکسی با /apps در انتهای URI و یک فعل POST ارسال شود، این شرط فعال می‌شود (و سیاست‌ها اجرا می‌شوند).

در پنل ناوبر، جریان‌های جدیدی را برای برنامه‌ها و توسعه‌دهندگان مشاهده خواهید کرد.

برای مشاهده پیکربندی جریان شرطی در نمای کد ویرایشگر پروکسی 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 پیاده‌سازی می‌شود. ( به پیکربندی جریان‌ها مراجعه کنید.)

پس از استقرار پروکسی API در محیط تست، درخواست زیر:

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

باعث می‌شود شرط به مقدار درست ارزیابی شود، و این جریان، همراه با هرگونه سیاست مرتبط، اجرا خواهد شد.

مثال شرط زیر از یک عبارت منظم جاوا برای تشخیص فراخوانی‌های انجام شده به منبع /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، می‌توانید از کاراکترهای عمومی (wildcards) استفاده کنید. برای مثال:

/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

در اینجا شرایط جریان شرطی در تعریف پروکسی 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 Community مورد بحث قرار گرفته است .

اگر ترجیح می‌دهید، می‌توانید بدون استفاده از 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" باشد و عبارت منظم "[az]" باشد، هیچ تطابقی وجود ندارد، زیرا "[az]" دقیقاً با یک کاراکتر الفبا مطابقت دارد. عبارت "[az]+" نیز مانند "[az]*" و "[az]{3}" کار می‌کند.

بیایید به یک مثال ملموس نگاه کنیم. فرض کنید سرور احراز هویت لیستی از نقش‌ها را به صورت رشته‌ای که با کاما از هم جدا شده است، برمی‌گرداند: "ویرایشگر، نویسنده، مهمان".

برای بررسی وجود نقش ویرایشگر، این ساختار کار نخواهد کرد، زیرا "ویرایشگر" تنها بخشی از کل رشته است.

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

با این حال، این ساختار کار خواهد کرد:

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

این روش کار می‌کند زیرا شکست کلمات و هر بخش دیگری از رشته با پیشوند و پسوند .* را در نظر می‌گیرد.

در این مثال، می‌توانید با استفاده از عملگر Matches، وجود "editor" را نیز بررسی کنید:

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

با این حال، در مواردی که به دقت بیشتری نیاز دارید، JavaRegex اغلب انتخاب بهتری است.

فرار از نقل قول‌های دوتایی در عبارات JavaRegex

سینتکس Condition ایجاب می‌کند که یک عبارت JavaRegex داخل علامت نقل قول دوتایی قرار گیرد؛ بنابراین، اگر یک عبارت Regex دارید که شامل علامت نقل قول دوتایی است، به یک روش جایگزین برای تطبیق آنها نیاز دارید. پاسخ Unicode است. برای مثال، فرض کنید یک هدر مانند زیر ارسال می‌کنید که شامل علامت نقل قول دوتایی است:
 -H 'content-type:multipart/related; type="application/xop+xml"'
اگر سعی کنید آن هدر را در یک شرط Regex مطابقت دهید، خطای شرط نامعتبر دریافت خواهید کرد زیرا عبارت شامل علامت نقل قول دوگانه است:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
راه حل این است که علامت نقل قول دوتایی مبتنی بر ASCII را با معادل یونیکد آنها، \u0022 ، جایگزین کنیم. برای مثال، عبارت زیر معتبر است و نتیجه مورد انتظار را تولید می‌کند:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"