قابلیت Message Mediation در WSO2 API Manager

Message mediation در WSO2 API Manager به معنای توانایی تغییر یا تبدیل پیام‌های ورودی و خروجی است که از یک API عبور می‌کند. این قابلیت به کاربران اجازه می‌دهد تا پیام‌ها را در زمان اجرا تغییر دهند و به صورت دلخواه تبدیل کنند. این امکان به مدیران API اجازه می‌دهد تا پیام‌های ورودی و خروجی را بر اساس نیازهای خود تغییر داده و به سادگی سفارشی‌سازی کنند.

با استفاده از Message Mediation در WSO2 API Manager، کاربران می‌توانند واسط‌های پیام‌دهی را برای تبدیل فرمت‌های پیام، افزودن یا حذف سرآیندها، و یا اعمال هرگونه منطق تجاری دلخواه، سفارشی‌سازی کنند. این قابلیت به کاربران این امکان را می‌دهد که به راحتی برای هماهنگ سازی API های خود با نیازهای سازمان خود، اقدام کنند و به سرعت و با کمترین هزینه، تغییرات لازم را اعمال کنند.

به طور خلاصه، Message Mediation در WSO2 API Manager یک قابلیت قدرتمند است که به کاربران این امکان را می‌دهد تا پیام‌های ورودی و خروجی را بر اساس نیازهای خود تغییر داده و سفارشی‌سازی کنند، و به راحتی تغییرات لازم را اعمال کنند. در ادامه این مطلب با شرکت دانش بنیان پلتکو همراه باشید.

API Policies

سیاست‌ها (policies) معمولاً برخی از منطق تجاری را اعمال می‌کنند که باید در جریان درخواست (request)، پاسخ (response) یا خطای فراخوانی (fault) API اجرا شوند.

یک سیاست، مجموعه­‌ای از قوانین است که در API Gateway اجرا می‌­شود. با استفاده از سیاست‌ها می‌توانیم فراخوانی APIها را قبل از رسیدن به endpoint، دستخوش تغییرات رفتاری جزئی کنیم. به روشی مشابه می‌توانیم پاسخ وب‌سرویسی که کاربر دریافت می‌کند را نیز تغییر دهیم.

سیاست به API Gateway که با WSO2 API Manager پیکربندی کرده­اید بستگی دارد. ویژگی پشتیبانی سیاست سطح عملیات از دو نوع gateway زیر پشتیبانی می­‌کند:

  • Regular Gateway (Synapse Gateway)
  • Choreo Connect

API Manager یک مجموعه پیش‌فرض از سیاست‌ها را ارائه می‌کند که بیش­تر موارد استفاده رایج را که به آن نیاز دارید، پوشش می‌دهد، در حالی که به شما امکان ایجاد سیاست را نیز می‌دهد. سه جریان اصلی تحت هر عملیات API وجود دارد که می­توانید از آن­ها برای پیوست­کردن هر سیاست مورد نیاز خود استفاده کنید. یعنی جریان درخواست(request)، جریان پاسخ(response) و جریان خطا(fault). همچنین می‌توانید چندین سیاست را تحت هر یک از این جریان‌ها ضمیمه کنید، و می‌توانید سیاست‌های پیوست را تعویض و تنظیم مجدد نمود.

برای یادآوری نکات ذکر شده، این ویژگی بهبود­یافته انعطاف­پذیری بسیار بیشتری را برای الزامات مدیریت سیاست شما می­دهد. به تغییرات معماری زیر که توسط این ویژگی ایجاد می­شود توجه کنید:

  • مفهوم پیوستن یک سیاست واحد به یک جریان خاص (یعنی درخواست، پاسخ یا خطا) در سطح API یک گلوگاه با نسخه‌های قبلی WSO2 API Manager بود.
  • با ویژگی جدید و بهبودیافته، می‌توانیم چندین سیاست را در سطح عملیاتی وصل کنیم، نه اینکه فقط یک سیاست را برای کل API ضمیمه کنیم.
  • ما می‌توانیم ترتیب درگیرشدن سیاست‌های پیوست­شده با API Gateway پیکربندی‌شده را دستکاری کنیم. ترتیبی که سیاست‌ها را بر اساس آن تنظیم کرده‌اید، تضمین می‌شود که توسط gateway رعایت شود.
  • به‌راحتی می‌توانید ورودی‌های پویا را برای متغیر‌های سیاست در مقابل سیاست‌های ثابتی که از طریق ویژگی سیاست‌های میانجی(mediation) منسوخ پشتیبانی می‌شوند، انتظار داشته باشید.

پیوست کردن سیاست ها

دستورالعمل‌های زیر را دنبال کنید تا یک یا چند سیاست پیش‌فرض که با WSO2 API Manager ارسال شده‌اند به یک عملیات API یک API موجود پیوست کنید.

1. وارد WSO2 API Publisher شوید: https://localhost:9490/publisher/apis

2. روی APIی که می‌خواهید سیاست‌ها را به آن پیوست کنید (مثلا PizzaShackAPI 1.0.0) کلیک کنید. به تنظیمات API → Policies بروید.

3. در بخش API Gateway، مطمئن شوید که gateway صحیح را انتخاب کنید. API Manager از دو نوع gateway زیر پشتیبانی می­کند: Regular Gateway (Synapse Gateway) و Choreo Connect. بسته به درگاهی که API شما در آن مستقر است، Gateway را انتخاب کنید.

 

سیاست های api

 

نکته: به خاطر داشته باشید که هنگام جابجایی بین gatewayها، سیاست‌های پیوست­شده تحت یک API Gateway معین حذف خواهند شد. با این حال، این حذف سیاست، تنها در صورتی در API شما منعکس می‌شود که روی دکمه save که در پایین صفحه سیاست‌ها یافت می‌شود، کلیک کنید.

نکته مهم:

لیست خط مشی به دروازه انتخابی بستگی دارد (یعنی لیست سیاست در زیر Regular gateway با Choreo Connect متفاوت است).

در زیر تفاوت‌­های کلیدی بین این دو نوع ذکر شده است:

Gateway

تفاوت‌­ها

Regular Gateway

دانه‌­بندی سطح عملیات

جریان های پشتیبانی شده تحت هر عملیات: درخواست، پاسخ، خطا

Choreo Connect

دانه‌­بندی سطح منابع

جریان­‌های پشتیبانی­ شده تحت هر منبع: درخواست، پاسخ

 

4. عملیات و جریان مورد نظر را که می­خواهید سیاست­ها را به آن ضمیمه کنید، انتخاب کنید. پس از تصمیم­گیری، می­توانید عملیات API را گسترش دهید.

در این مرحله متوجه خواهید شد که به طور پیش‌فرض رابط­کاربری اولین عملیات API را در بازدید اولیه از صفحه باز می‌کند (برای PizzaShack API، /order POST به طور پیش‌فرض گسترش می‌یابد).

5. بیایید یک سیاست را به عملیات /menu در GET ضمیمه کنیم. در ستون سمت چپ UI به پایین اسکرول کنید و بر روی /menu در GET کلیک کنید. هنگامی که عملیات API گسترش می­یابد، باید بتوانید صفحه زیر را ببینید.

 

سیاست های api

 

6. سیاست Add Header را از زبانه Request در لیست Policy بکشید و آن را به قسمت dropzone جریان درخواست از /menu عملیات GET رها کنید.

متوجه خواهید شد که یک پنل جانبی از سمت راست ظاهر می­شود. جزئیات مورد نیاز را با استفاده از مقادیر ارائه شده در زیر پر کنید. سپس، روی save کلیک کنید.

Field

مقدار نمونه

Header Name

Foo

Header Value

Bar

نکته: می‌توانید به‌صورت اختیاری از گزینه اعمال به همه منابع استفاده کنید تا هنگام ذخیره تنظیمات، سیاست یکسانی را به همه منابع پیوست کنید. این خط مشی یکسان را به همه عملیات API به همراه مقادیری که برای پیکربندی خط مشی وارد کرده اید (در صورت وجود) متصل می کند.

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

7. اکنون که سیاست حذف‌شده را ذخیره کرده‌ایم، باید بتوانید سیاست Add Header پیوست­شده (با حروف اول AH) را ببینید.

 

api policies

 

8. اگر روی این سیاست AH (یعنی افزودن header) به تازگی پیوست­شده کلیک کنید، همچنان باید بتوانید مقادیری را که در ابتدا وارد کرده اید مشاهده/ویرایش کنید.

 

سیاست های api

 

9. بیایید ادامه دهیم و چند سیاست دیگر را به همان جریان درخواست پیوست کنیم. هر مقدار از سیاست­ها را از برگه درخواست لیست سیاست انتخاب کنید.

 

api policies

 

نکته:

  • می‌توانید سیاست‌های حذف‌شده را که به جریان درخواست از menu / GET پیوست شده‌اند، دوباره مرتب کنید.
  • می‌توانید منبع سیاست را به‌عنوان یک فایل zip. با کلیک­کردن روی نماد دانلود ابری دانلود کنید.
  • اگر روی نماد حذف کلیک کنید، سیاست حذف شده، لغو می شود.

 

10. در نهایت، وقتی با کشیدن و انداختن (drag and drop) سیاست­ها، به هدف خود رسیدید، می‌توانید ادامه دهید و روی دکمه ذخیره در پایین صفحه کلیک کنید.

توجه داشته باشید که اگر روی ذخیره کلیک نکنید، هیچ یک از سیاست های حذف شده در API ذخیره نمی شود.

 

api manager

ایجاد یک سیاست

در زیر دو راه برای ایجاد یک سیاست جدید ذکر شده است. بسته به اینکه آیا نیاز دارید که این سیاست فقط در یک API خاص قابل دسترسی باشد یا برای همه APIها در دسترس باشد، می توانید در مورد گزینه­ای که باید دنبال کنید تصمیم بگیرید.

ایجاد سیاست مشترک

یک سیاست مشترک یک سیاست کلی (global) است و شما می­توانید به راحتی از این سیاست در سطح عملیات هر API دلخواه استفاده کنید. توجه داشته باشید که این سیاست‌ها به هیچ API محدود نمی‌شوند و صرفاً الگوهایی هستند که می‌توانید به راحتی از آن­ها استفاده کنید.

حال بیایید ببینیم چگونه می­توانید چنین سیاستی ایجاد کنید. دستورالعمل­‌های زیر را برای ایجاد یک سیاست مشترک جدید دنبال کنید:

1. وارد WSO2 API Publisher شوید: https://localhost:9490/publisher/.

2. از منوی سمت چپ به تب Policies بروید و روی Add New Policy کلیک کنید. فهرست سیاست مشترک بسته به API Gateway انتخابی متفاوت خواهد بود.

 api policies

 

3. بیایید یک سیاست به نام Sample Add Header برای هدف demo ایجاد کنیم. ابتدا بخش General Details را با استفاده از جزئیات زیر پر می­کنیم.

 

api manager

 

4. در ادامه به قسمت Gateway Specific Details می­رویم. اینجاست که فایل سیاست را که حاوی منطق تجاری سیاست است آپلود می­کنیم.

سیاست نمونه­ای که ما در این­جا ایجاد می­کنیم برای Regular Gateway (Gateway Synapse) خواهد بود و از این رو، سیاست باید یک فایل .j2 یا xml. باشد.

برای پرکردن این بخش از فرم از جدول زیر استفاده کنید.

 

Field Sample Value
Gateway های پشتیبانی شده Regular Gateway
آپلود فایل سیاست

محتوای زیر را در فایلی به نام sampleAddHeader.j2 کپی کرده و آپلود کنید.(از xml هم می­توانید استفاده کنید)

<property action=”set” name=”{{headerName}}” value=”{{headerValue}}” scope=”transport” />

 

سیاست های api

5. آخرین بخش در فرم بخش ویژگی ­های سیاست (Policy Attributes) است. این ویژگی­ها از فایل سیاستی که در مرحله قبل آپلود کردید مشتق شده­اند. اگر محتوای سیاست را مشاهده کنید، باید متوجه دو مقدار پویا در آن سیاست شوید، یعنی headerName و headerValue.

اینها ویژگی‌هایی هستند که باید هنگام ایجاد سیاست خود، وارد کنیم (توجه داشته باشید که اگر محتوای سیاست ثابت است، می‌توانید یک سیاست ثابت و بدون ویژگی داشته باشید).

بیایید بخش ویژگی­های سیاست را با استفاده از جزئیات زیر پر کنیم:

 

api policies

 

ویژگی 1 (Attribute 1)

Field Sample Value
Name headerName
Display Name(نام نمایشی) Header Name
Required(اجباری) True
Description(توضیحات) Name of the Header to be added
Type(نوع متغیر) String
Validation Regex(عبارت منظم معتبر)
^([a-zA-Z_][a-zA-Z\d_\-\ ]*)$
Default Value(عبارت پیش­فرض)

Leave this blank

 

 

ویژگی2 (Attribute 2)

Field Sample Value
Name headerValue
Display Name(نام نمایشی) Header Value
Required(اجباری) True
Description(توضیحات) Value of the Header to be added
Type(نوع متغیر) String
Validation Regex(عبارت منظم معتبر)
^([a-zA-Z_][a-zA-Z\d_\-\ ]*)$
Default Value(عبارت پیش­فرض)

Leave this blank

 

 

6. پس از انجام این کار، فرم تکمیل شده باید مانند تصویر زیر باشد. اکنون می­توانیم روی Save کلیک کنیم.

 

ایجاد سیاست api

 

7. اکنون سیاست جدید ایجاد شده در جدول ظاهر می شود. برای تأیید می­توانید ادامه دهید و این سیاست را جستجو کنید.

 

8. با کلیک بر روی عملView سعی کنید این سیاست را مشاهده کنید. توجه داشته باشید که با­استفاده از دکمه Download Policy می­توانید این سیاست را به صورت فایل zip. دانلود کنید.

 

ایجاد سیاست api خاص

 

ایجاد سیاست برای API خاص

اگر ترجیح می­دهید سیاست محلی (local) برای API ایجاد کنید، می­توانید مراحل ارائه شده زیر را برای ایجاد چنین سیاستی دنبال کنید.

1. وارد WSO2 API Publisher شوید: https://localhost:9490/publisher/

2.روی هر API (به عنوان مثال، PizzaShackAPI 1.0.0) کلیک کنید و به برگه سیاست­ها بروید. صفحه­ای مانند زیر را مشاهده خواهید کرد. برای ایجاد یک سیاست خاص API روی دکمه Add New Policy کلیک کنید.

 

ایجاد سیاست یک API خاص

 

3. سپس از شما خواسته می شود که جزئیات سیاست را وارد کنید. بیایید این سیاست خاص API را به عنوان Local Add Header نام­گذاری کنیم.

لطفاً برای پر­کردن بقیه فرم به مراحل 3 تا 5 از راهنمای ایجاد سیاست مشترک بالا مراجعه کنید. فرم کاملاً پر­شده باید مانند تصویر زیر باشد.

سپس بر روی Save کلیک کنید.

ایجاد سیاست برای API خاص

 

4. شما باید بتوانید یک سیاست به نام Local Add Header را در برگه Request و برگه Response در Policy List مشاهده کنید.

ایجاد سیاست برای API خاص

 

5. هنگامی که نشانگر موس را روی سیاست Local Add Header آوردید، باید بتوانید آیکن مشاهده و آیکن حذف را همان­طور که در تصویر زیر نشان داده شده است، ببینید.

ایجاد سیاست برای API خاص

  • اگر روی عملکرد مشاهده (چشم) کلیک کنید، یک فرم سیاست پر­شده با جزئیاتی که وارد کرده­اید از شما خواسته می­شود.
  • اگر تصمیم به حذف سیاست دارید، می‌توانید بر روی عملکرد حذف (سطل زباله) که در کنار سیاست ظاهر می‌شود، کلیک کنید. قبل از حذف سیاست خاص API، رضایت شما را می­خواهد. در صورت تایید آن سیاست حذف خواهد شد.

نکته:

برای سیاست‌های مشترک فقط عملکرد مشاهده پشتیبانی شده است، برخلاف سیاست‌های خاص API، که هر دو عملکرد مشاهده و حذف را پشتیبانی می‌کنند. اگر می خواهید یک سیاست مشترک را حذف کنید، برای انجام این کار باید به فهرست سیاست  مشترک ذخیره‌ شده در پنل سیاست‌های کلی (global) بروید.

Regular Gateway Policies(سیاست­های gateway منظم)

Add Dynamic Endpoints(اضافه کردن نقطه پایانی پویا)

 

شما نمی­توانید به صورت پویا endpoint (نقطه پایانی) یک API را با استفاده از نقاط انتهایی آدرس در WSO2 API Manager بسازید. برای دستیابی به نیاز یک نقطه پایانی پویا، می­توانید به جای آن از نقطه پایانی پیش­فرض استفاده کنید.

 

ایجاد سیاست برای API خاص

 

نقطه پایانی پیش­فرض(default endpoint)، پیام را به آدرس مشخص­شده در headerی به نام To ارسال می کند. هدر To می­تواند به صورت پویا ساخته شود. یک مثال در زیر داده شده است:

<sequence xmlns=“http://ws.apache.org/ns/synapse” name=“default-endpoint-seq“>

    <property name=“service_ep” expression=“fn:concat(‘http://jsonplaceholder.typicode.com/’, ‘posts/‘)”/>

    <header name=“To” expression=“get-property(‘service_ep”)”/>

</sequence>

در این مثال، شما ویژگی service_ep را به صورت پویا ساخته‌­اید و مقدار این ویژگی را به هِدِر To اختصاص داده‌اید. نقطه ­پایانی پیش­فرض پیام را به آدرس مشخص ­شده در هدر To ارسال می­کند، در این مورد،

http://jsonplaceholder.typicode.com/posts.

اطلاع: عملکرد نقطه­ پایانی پویا برای سناریوهایی مناسب است که در آن client application می­تواند یک attribute را در درخواست مرتبط با نقطه­ پایانی مورد نظر ارسال کند (مانند HTTP transport header یا به عنوان بخشی از payload) که می­تواند در mediation extension استفاده شود.

نکته: mediation extension برای همه منابع API اعمال می­شود. بنابراین، همه منابع(GET, POST, …)، دارای منطقی مشابه برای ساخت نقطه پایانی خواهند بود.

می­توانید محتوای دنباله بالا را در یک فایل XML کپی کنید و آن را در یک API پیکربندی­شده با نقطه پایانی پویا با استفاده از پورتال publisher آپلود کنید.

حذف request header خاص از response (Removing specific Request Headers From Response)

سرویس های وب ممکن است حاوی header های پاسخ با اطلاعات حساس باشند. در ادامه نحوه حذف header های درخواست HTTP از response ها به دلایل امنیتی توضیح داده شده است.

برای حذف header ‌های درخواست از response ‌ها برای هر API یا در سطح کلی، نام header را که باید حذف شود به‌عنوان یک property در out sequence سفارشی خود اضافه کنید.

باتوجه به الگوی زیر property را پیاده­ سازی نمایید.

<property name=“<name of the header to be removed>” scope=“transport” action=“remove>

به نمونه زیر که از الگوی بالا پیروی می­کند، توجه نمایید:

<  /property name=CustomTransportHeader” scope=“transport” action=“remove>

 

برای آشنایی با نحوه افزودن سیاست بالا به ازای هر API یا در سطح کلی، ایجاد یک سیاست را بررسی کنید.

ارسال یک authorization token سفارشی به Backend (Passing a Custom Authorization Token to the Backend)

هنگامی که یک درخواست API را به سرور ارسال می­کنید، یک توکن را در authorization header درخواست ارسال می­کنید. API Gateway از این token برای اجازه دسترسی استفاده می­کند و سپس آن را از پیام خروجی حذف می­کند. اگر می‌خواهید از یک authorization token متفاوت (یا یک توکن سفارشی تولید شده) نسبت به access token ایجاد شده از برنامه استفاده کنید، می‌توانید از آن به عنوان مکانیزم تبادل توکن در منطق mediation API استفاده کنید. در این آموزش، نحوه ارسال یک authorization token سفارشی را توضیح می­دهیم که با authorization token تولید شده برای برنامه متفاوت است.

در این آموزش، شما یک نمونه سرور JAX-RS دارید و این سرور همیشه انتظار 1234 را به عنوان authorization token دارد. در درخواست API خود، توکنی را که در header Authorization تولید می‌شود و 1234 را در header سفارشی ارسال می‌کنید. پسوند mediation که می‌نویسید، مقدار header سفارشی را استخراج می‌کند و قبل از ارسال آن به سرور، آن را به‌عنوان authorization header تنظیم می‌کند.

به طور خلاصه:

کلاینت(headers: Authorization, Custom) ç Gateway (حذف Authorization و تبدیل Custom به Authorization) ç سرور

این برای این است که هم در Gateway احراز هویت انجام شود و هم در سرور.

1.محتوای sequence زیر را به یک فایل اضافه کنید و آن را به عنوان xml ذخیره کنید.

<sequence xmlns=“http://ws.apache.org/ns/synapse” name=“TokenExchange“>

    <property name=“Custom” expression=“get-property(‘transport’, ‘Custom’)”/>

    <property name=“Authorization” expression=“get-property(‘Custom’)” scope=“transport“/>

    <property name=“Custom” scope=“transport” action=“remove“/>

</sequence>

2. وارد API Publisher شوید، یک REST API جدید با اطلاعات داده شده بسازید.

 

field Sample value
name TestCustomHeader
Context /testcustomheader
Version 1.0.0
Business Plan Gold
Endpoint http://wso2cloud-custom-auth-header-sample-1-0-0.wso2apps.com/custom-auth-header/validate-header

3. به برگه API Configuration → Policies بروید. با پیروی از دستورالعمل‌های ایجاد سیاست، یک سیاست جدید با اطلاعات ارائه شده در جدول زیر ایجاد کنید.

 

قسمت Field مقدار نمونه
General Details Name Custom Authorization Token
Description Passing a custom authorization token to the backend
Applicable Flows Request
Gateway Specific Details Supported Gateways Regular Gateway
Policy File tokenExchange.xml  file
Plicicy Attributes N/A N/A

 

4. در مرحله بعد، سیاست Custom Authorization Token را که به تازگی با دنبال کردن مرحله 3 ایجاد کرده­اید، از برگه Request، لیست سیاست پیدا کنید.

با دنبال­کردن دستورالعمل‌ها در پیوست­ کردن سیاست، این سیاست را به عملیات(های) API مورد نظر بکشید و رها کنید(drag and drop).

 

ایجاد سیاست یک API خاص

 

5. در نهایت، روی دکمه Save کلیک کنید تا سیاست­های پیوست ­شده در API اعمال شود.

 

ایجاد سیاست یک API خاص

6. مطمئن شوید که به تب Deployments رفته و روی دکمه Deploy New Revision کلیک کنید. همچنین، اگر API در حالت PUBLISHED نیست، به تب Lifecycle بروید و API خود را منتشر کنید.

7. به Developer Portal بروید، مشترک شوید و یک توکن برای فراخوانی API منتشر شده دریافت کنید.

نکته: دستورالعمل های موجود در اینجا را برای ایجاد یک access token برنامه دنبال کنید.

8. هر کلاینت REST را در دستگاه خود نصب کنید. ما در اینجا از cURL استفاده می­کنیم.

9. به command line بروید و API را با استفاده از دستور cURL زیر فراخوانی کنید.

در این دستور، توکنی را که backend انتظار دارد، یعنی 1234، در header Custom باauthorization token که سیستم در header Authorization تولید می­کند، ارسال می­کنید.

الگو:

curl -H “Authorization: Bearer <access token>” -H “Custom: Bearer 1234” <API URL>

نمونه:

curl -k -H “Authorization: Bearer 2e25097b2b3fbbfb44f5642fa8a495a1” -H “Custom: Bearer 1234” https://localhost:8243/testcustomheader/1.0.0

اطلاعات: اگر از https استفاده می­کنید، از -k در دستور cURL استفاده کنید.

 

10. به پاسخی که در command line دریافت می­کنید توجه کنید. با توجه به نمونه سرور استفاده­ شده در این آموزش، شما پاسخ را به عنوان “درخواست دریافت شد” دریافت می­‌کنید.

 در این آموزش، یک توکن سفارشی که backend انتظار دارد را همراه با authorziation token تولید شده توسط سیستم ارسال کردید و با تعویض توکن سیستم با توکن سفارشی خود، یک API را با موفقیت فراخوانی کردید.

این مطلب چقدر مفید بود ؟

روی یک ستاره کلیک کنید تا به آن امتیاز دهید

میانگین امتیاز / 5. نتایج آرا:

تاکنون رأی ندارید! اولین نفری باشید که به این پست امتیاز می دهد.

بدون دیدگاه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *