افزودن پشتیبانی CORS به پروکسی API

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

CORS (اشتراک‌گذاری منابع متقاطع) مکانیزم استانداردی است که به فراخوان‌های JavaScript XMLHttpRequest (XHR) اجازه می‌دهد تا در یک صفحه وب با منابعی از دامنه‌های غیر اصلی تعامل داشته باشند. CORS راه حلی است که معمولاً برای " خط مشی همان مبدأ " اجرا می شود که توسط همه مرورگرها اجرا می شود. به عنوان مثال، اگر از طریق اجرای کد جاوا اسکریپت در مرورگر خود، با API توییتر تماس XHR برقرار کنید، تماس با شکست مواجه خواهد شد. این به این دلیل است که دامنه ای که صفحه را به مرورگر شما ارائه می دهد با دامنه ای که به API Twitter سرویس می دهد یکسان نیست. CORS راه حلی برای این مشکل فراهم می کند و به سرورها اجازه می دهد در صورت تمایل به اشتراک گذاری منابع متقاطع، "انتخاب کنند".

ویدئو: برای یادگیری نحوه فعال کردن CORS در یک پروکسی API، یک ویدیوی کوتاه تماشا کنید.

مورد استفاده معمولی برای CORS

کد JQuery زیر یک سرویس هدف ساختگی را فراخوانی می کند. اگر از درون زمینه یک مرورگر (یک صفحه وب) اجرا شود، تماس به دلیل خط مشی مبدأ یکسان با شکست مواجه خواهد شد:

<script>
var url = "http://service.example.com";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This is where we end up!
            }
    });
  });
});
</script>

یکی از راه حل های این مشکل ایجاد یک پراکسی Apigee API است که سرویس API را در انتهای پشتی صدا می کند. به یاد داشته باشید که Edge بین کلاینت (در این مورد یک مرورگر) و API پشتیبان (سرویس) قرار دارد. از آنجایی که پروکسی API بر روی سرور اجرا می‌شود، نه در مرورگر، می‌تواند سرویس را با موفقیت فراخوانی کند. سپس، تنها کاری که باید انجام دهید این است که هدرهای CORS را به پاسخ TargetEndpoint متصل کنید. تا زمانی که مرورگر از CORS پشتیبانی می کند، این هدرها به مرورگر سیگنال می دهند که اشکالی ندارد که خط مشی همان مبدأ خود را "آرام" کند و به فراخوانی API متقاطع اجازه می دهد تا موفق شود.

هنگامی که پروکسی با پشتیبانی CORS ایجاد شد، می توانید به جای سرویس backend در کد سمت سرویس گیرنده خود، URL پروکسی API را فراخوانی کنید. به عنوان مثال:

<script>
var url = "http://myorg-test.apigee.net/v1/example";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This time, we do not end up here!
            }
    });
  });
});
</script>

پیوست کردن خط مشی افزودن CORS به پروکسی API جدید

هنگام ایجاد پروکسی API، می‌توانید با پیوست کردن خط‌مشی «افزودن CORS» به پروکسی API، پشتیبانی CORS را به آن اضافه کنید. برای افزودن این خط‌مشی، کادر افزودن سرصفحه‌های CORS را در صفحه امنیتی جادوگر ساخت پروکسی انتخاب کنید.

هنگامی که این کادر را انتخاب می کنید، سیاستی به نام افزودن CORS به طور خودکار به سیستم اضافه می شود و به پیش جریان پاسخ TargetEndpoint متصل می شود، همانطور که در شکل زیر نشان داده شده است:

خط‌مشی CORS را در قسمت خط‌مشی‌ها به ناوبری اضافه کنید و به پیش جریان پاسخ TargetEndpoint در پان راست پیوست کنید

خط مشی Add CORS به عنوان یک خط مشی AssignMessage اجرا می شود که هدرهای مناسب را به پاسخ اضافه می کند. اساساً، هدرها به مرورگر اجازه می‌دهند که بداند منابع خود را با کدام منبع به اشتراک می‌گذارد، چه روش‌هایی را می‌پذیرد و غیره. می‌توانید درباره این سرصفحه‌های CORS در توصیه W3C به اشتراک گذاری منابع Cross-Origin بیشتر بخوانید.

شما باید خط مشی را به صورت زیر تغییر دهید:

  • همانطور که در گزیده کد زیر نشان داده شده است، هدرهای content-type و authorization (که برای پشتیبانی از احراز هویت اولیه یا OAuth2 لازم است) را به هدر Access-Control-Allow-Headers اضافه کنید.
  • برای احراز هویت OAuth2، ممکن است لازم باشد اقداماتی را برای اصلاح رفتارهای غیرمنطبق با RFC انجام دهید.
  • توصیه می شود از <Set> برای تنظیم سرصفحه های CORS به جای <Add> استفاده کنید، همانطور که در گزیده زیر نشان داده شده است. هنگام استفاده از <Add> ، اگر هدر Access-Control-Allow-Origin از قبل وجود داشته باشد، خطای زیر را دریافت خواهید کرد:

    The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

    برای اطلاعات بیشتر، خطای CORS را ببینید: سرصفحه حاوی چندین مقدار "*، *" است، اما تنها یک مورد مجاز است .

<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <FaultRules/>
    <Properties/>
    <Set>
        <Headers>
            <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, authorization</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

افزودن سرصفحه های CORS به یک پروکسی موجود

شما باید به صورت دستی یک خط مشی Assign Message جدید ایجاد کنید و کد مربوط به سیاست Add CORS فهرست شده در بخش قبلی را در آن کپی کنید. سپس، خط مشی را به پیش جریان پاسخ TargetEndpoint پروکسی API متصل کنید. در صورت نیاز می توانید مقادیر هدر را تغییر دهید. برای اطلاعات بیشتر در مورد ایجاد و پیوست کردن خط‌مشی‌ها، به خط مشی چیست مراجعه کنید؟ .

رسیدگی به درخواست های پیش از پرواز CORS

CORS preflight به ارسال یک درخواست به سرور برای تأیید اینکه آیا از CORS پشتیبانی می کند یا خیر، اشاره دارد. پاسخ‌های معمولی قبل از پرواز شامل مبداهایی است که سرور درخواست‌های CORS را می‌پذیرد، فهرستی از روش‌های HTTP که برای درخواست‌های CORS پشتیبانی می‌شوند، سرصفحه‌هایی که می‌توانند به عنوان بخشی از درخواست منبع استفاده شوند، حداکثر زمان پاسخ قبل از پرواز در حافظه پنهان و موارد دیگر. اگر سرویس پشتیبانی CORS را نشان ندهد یا مایل به پذیرش درخواست‌های مبدأ متقابل از مبدأ مشتری نباشد، خط‌مشی مبدأ متقاطع مرورگر اعمال می‌شود و هرگونه درخواست بین دامنه‌ای از مشتری برای تعامل با منابع میزبانی شده در آن انجام می‌شود. آن سرور از کار خواهد افتاد.

به طور معمول، درخواست های CORS قبل از پرواز با روش HTTP OPTIONS انجام می شود. وقتی سروری که از CORS پشتیبانی می‌کند، درخواست OPTIONS را دریافت می‌کند، مجموعه‌ای از سرصفحه‌های CORS را به مشتری برمی‌گرداند که سطح پشتیبانی CORS را نشان می‌دهد. در نتیجه این دست دادن، مشتری می داند که مجاز است از دامنه غیر مبدأ چه چیزی درخواست کند.

برای اطلاعات بیشتر در مورد قبل از پرواز، به توصیه W3C به اشتراک گذاری منابع Cross-Origin مراجعه کنید. علاوه بر این، وبلاگ ها و مقالات متعددی در مورد CORS وجود دارد که می توانید به آنها مراجعه کنید.

Apigee یک راه حل CORS قبل از پرواز خارج از جعبه را شامل نمی شود، اما امکان پیاده سازی آن، همانطور که در این بخش توضیح داده شده است، وجود دارد. هدف این است که پروکسی یک درخواست OPTIONS را در یک جریان شرطی ارزیابی کند. سپس پروکسی می تواند پاسخ مناسب را به مشتری ارسال کند.

بیایید به یک جریان نمونه نگاه کنیم، و سپس در مورد قسمت هایی که درخواست قبل از پرواز را انجام می دهند، بحث کنیم:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows>
        <Flow name="OptionsPreFlight">
            <Request/>
            <Response>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </Response>
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
        </Flow>
    </Flows>

    <PreFlow name="PreFlow">
        <Request/>
        <Response/>

    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/v1/cnc</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
   </RouteRule>
   <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</ProxyEndpoint>

بخش های کلیدی این ProxyEndpoint به شرح زیر است:

  • یک RouteRule برای یک هدف NULL با یک شرط برای درخواست OPTIONS ایجاد می شود. توجه داشته باشید که TargetEndpoint مشخص نشده است. اگر درخواست OPTIONS دریافت شود و سرصفحه‌های درخواست Origin و Access-Control-Request-Method پوچ نباشند، پروکسی بلافاصله سرصفحه‌های CORS را در یک پاسخ به کلاینت برمی‌گرداند (با دور زدن هدف پیش‌فرض "پشتیبان" واقعی). برای جزئیات در مورد شرایط جریان و RouteRule، به شرایط با متغیرهای جریان مراجعه کنید.

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • یک جریان OptionsPreFlight ایجاد می‌شود که در صورت دریافت درخواست OPTIONS و تهی نبودن سرصفحه‌های درخواست Origin و Access-Control-Request-Method، یک خط‌مشی Add CORS، حاوی سرصفحه‌های CORS، به جریان اضافه می‌کند.

     <Flow name="OptionsPreFlight">
                <Request/>
                <Response>
                    <Step>
                        <Name>add-cors</Name>
                    </Step>
                </Response>
            <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
     </Flow>
    

با استفاده از نمونه محلول CORS

یک نمونه راه حل CORS، پیاده سازی شده به عنوان یک جریان مشترک، در GitHub موجود است. بسته جریان مشترک را به محیط خود وارد کنید و آن را با استفاده از قلاب‌های جریان یا مستقیماً به جریان‌های پراکسی API متصل کنید. برای جزئیات، فایل CORS-Shared-Flow README ارائه شده به همراه نمونه را ببینید.