پروتکل HTTP چیست؟ — به زبان ساده

۵۱۲۹ بازدید
آخرین به‌روزرسانی: ۲۰ اردیبهشت ۱۴۰۲
زمان مطالعه: ۱۰ دقیقه
پروتکل HTTP چیست؟ — به زبان ساده

HTTP پروتکلی است که امکان واکشی منابعی از قبیل سند‌های HTML را به ما می‌دهد. HTTP مبنای هر نوع مبادله داده روی وب را تشکیل می‌دهد و یک پروتکل کلاینت-سرور است، یعنی درخواست‌ها از سوی گیرنده آغاز می‌شوند که عموماً یک مرورگر وب است. به این ترتیب یک سند کامل با ترکیب سند‌های کوچک و جزئی واکشی شده مانند متن، توضیح چیدمان، تصاویر، ویدئوها، اسکریپت‌ها و موارد دیگر در مرورگر وب بازسازی می‌شود. در این مقاله به توضیح پروتکل HTTP و اجزا و طرز کار آن خواهیم پرداخت.

مفهوم پروتکل

قبل از آن که پروتکل HTTP را توضیح دهیم، ابتدا بهتر است با خود مفهوم پروتکل آشنا شویم. پروتکل (اینترنتی) به سیستمی از قواعد گفته می‌شود که شیوه تبادل داده‌ها را در درون یا بین رایانه‌ها تعریف می‌کند. ارتباط بین دستگاه‌ها نیازمند این است که دستگاه‌ها روی قالب داده‌هایی که به مبادله می‌پردازند، توافق داشته باشند. مجموعه قواعدی که قالب این داده‌ها را تعریف می‌کنند، پروتکل نام دارند.

مقدمه پروتکل HTTP

کلاینت‌ها و سرورها از طریق مبادله پیام‌های منفرد (بر عکس جریان داده‌ها) با هم ارتباط می‌گیرند. این پیام‌ها از سوی کلاینت ارسال می‌شوند که عموماً یک مرورگر وب است و «درخواست» (Request) نام دارند. از سوی دیگر پیام‌هایی که از سوی سرور ارسال می‌شوند، «پاسخ» (Response) نامیده می‌شوند.

پروتکل HTTP

پروتکل HTTP در اوایل دهه 1990 میلادی تعریف شده و یک پروتکل قابل بسط است که در طی زمان تکامل یافته است. این پروتکل در لایه اپلیکیشن شبکه قرار دارد و روی اتصال TCP یا روی یک اتصال TCP رمزنگاری شده با TLS ارسال می‌شود. با این حال هر پروتکل انتقال پایداری می‌تواند به این منظور مورد استفاده قرار گیرد. پروتکل HTTP با توجه به بسط‌پذیری خود نه تنها برای واکشی اسناد «ابرمتن» (Hypertext)، بلکه برای واکشی اسناد و تصاویر یا برای ارسال محتوا به سرورها مانند نتایج یک فرم HTML نیز استفاده می‌شود. از پروتکل HTTP می‌توان برای واکشی بخش‌هایی از سند برای به‌روزرسانی صفحه‌های وب بنا به تقاضا نیز استفاده کرد.

اجزای سیستم‌های مبتنی بر HTTP

HTTP یک پروتکل کلاینت-سرور است، یعنی درخواست‌ها از سوی یک نهاد ارسال می‌شوند که «عامل کاربر» (user-agent) و یا واسطه وی است. در اغلب موارد این عامل کاربر یک مرورگر وب است، اما در عمل می‌تواند هر چیز دیگری نیز باشد. برای نمونه یک ربات که وب را خزش می‌کند تا ایندکس یک موتور جستجو را گردآوری کرده و نگهداری کند نیز می‌تواند از این پروتکل بهره بگیرد.

هر درخواست منفرد روی یک سرور ارسال می‌شود که آن را اداره می‌کند و یک پاسخ ارائه می‌دهد که response نام دارد. البته بین کلاینت و سرور، نهادهای زیادی وجود دارند که در مجموع «واسطه‌ها» (proxies) نام دارند و عملیات متفاوتی را اجرا کرده و برای نمونه به عنوان یک گیت‌وی یا کش عمل می‌کنند.

پروتکل HTTP

در عمل بین یک مرورگر و سرور برخی رایانه‌های قرار می‌گیرند که درخواست کاربر را اداره می‌کنند که شامل روترها، مودم‌ها و موارد دیگر می‌شود. به لطف طراحی لایه‌بندی‌شده وب، این موارد در لایه‌های شبکه و انتقال پنهان شده‌اند. HTTP در لایه بالا یعنی لایه اپلیکیشن قرار می‌گیرد. با این که عیب‌یابی مشکلات شبکه حائز اهمیت است، اما لایه‌های زیرین غالباً ارتباطی با توضیح HTTP ندارد.

کلاینت: عامل کاربر

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

مرورگر «همیشه» آن نهادی است که درخواست را آغاز می‌کند. بنابراین سرور هرگز آغازگر تبادل پیام نیست، گرچه در طی سال‌های اخیر برخی مکانیسم‌هایی به HTTP اضافه شده‌اند که پیام‌های آغازشده از سوی سرور را شبیه‌سازی می‌کنند.

مرورگر برای عرضه یک صفحه وب، درخواستی ابتدایی جهت واکشی سند HTML ارسال می‌کند که یک بازنمایی از صفحه است. سپس این فایل تحلیل می‌شود و درخواست‌های متناظر دیگری برای اجرای اسکریپت‌ها، اطلاعات چیدمان صفحه (CSS) و منابع فرعی قرار گرفته درون صفحه (که عموماً شامل تصاویر و ویدئوها است) ارائه می‌شود. در ادامه مرورگر وب این منابع را با هم ترکیب می‌کند تا یک سند کامل را به کاربر عرضه کند که «صفحه وب» نامیده می‌شود. اسکریپت‌های اجرا شده از سوی مرورگر می‌توانند منابع بیشتری را در فازهای بعدی واکشی کنند و مرورگر بر همین اساس صفحه وب را به‌روزرسانی می‌کند.

یک صفحه وب به سند «ابرمتن» گفته می‌شود. این بدان معنی است که برخی بخش‌های متن نمایش یافته، لینک‌هایی هستند که می‌توانند فعال شوند (که به طور معمول با کلیک ماوس انجام می‌یابد) تا یک صفحه وب واکشی شود. به این ترتیب کاربر می‌تواند «عامل کاربر» خود را هدایت کند و در وب به گردش بپردازد. مرورگر این جهت‌ها را در درخواست‌های HTTP ترجمه و در ادامه پاسخ‌های HTTP را تفسیر می‌کند تا یک پاسخ روشن به کاربر ارائه کند.

وب سرور

در سمت دیگر این کانال ارتباطی یک سرور قرار دارد که اسناد درخواستی از سوی کاربر را عرضه می‌کند. سرور مجازاً به صورت یک رایانه منفرد ظاهر می‌شود، اما ممکن است مجموعه‌ای از سرورها باشند که بار کاری را با هم به اشتراک بگذارند یا یک نرم‌افزار پیچیده باشد که از رایانه‌های دیگر که مسئول بخش‌های کش، پایگاه داده، یا سرورهای e-commerce پرس‌وجو کرده و سند را بسته به تقاضا به صورت کامل یا جزء به جزء تولید می‌کند.

سرور لزوماً یک رایانه منفرد نیست، بلکه چند وهله نرم‌افزاری مختلف سرور می‌توانند روی یک رایانه منفرد میزبانی شوند. با استفاده از نسخه 1.1 پروتکل HTTP و هدر Host حتی امکان اشتراک نشانی IP یکسان نیز وجود دارد.

واسطه‌ها

بین مرورگر وب و سرور، رایانه‌ها و دستگاه‌های بسیار زیادی قرار می‌گیرند که پیام‌های HTTP را رله می‌کنند. به دلیل ساختار لایه‌بندی‌شده وب، اغلب این دستگاه‌ها روی لایه «انتقال» (Transport) یا «شبکه» (Network) یا لایه «فیزیکی» (Physical) عمل می‌کنند و در HTTP نمایش می‌یابند و از این رو می‌توانند تأثیر عمده‌ای روی عملکرد داشته باشند. عناصری که روی لایه‌های اپلیکیشن عمل می‌کنند، عموماً «واسطه‌ها» (Proxies) نامیده می‌شوند. این موارد می‌توانند شفاف باشند و درخواست‌هایی که دریافت می‌کنند را بدون هیچ گونه دستکاری، فوروارد کنند یا این که غیر شفاف باشند و در این حالت درخواست را پیش از ارسال به سمت سرور مورد نوعی تغییر قرار می‌دهند. واسطه‌ها می‌توانند کارکردهای زیادی را اجرا کنند.

  • کش کردن (کش می‌تواند عمومی یا خصوصی مانند کش مرورگر باشد)
  • فیلترینگ (مانند اسکن آنتی‌ویروس یا کنترل والدین)
  • متعادل‌سازی بار (یا Load Balancing به چندین سرور امکان می‌دهد که درخواست‌های مختلف را پاسخ دهند)
  • احراز هویت (برای کنترل دسترسی به منابع مختلف استفاده می‌شود)
  • لاگ کردن (امکان ذخیره اطلاعات تاریخی را فراهم می‌سازد)

جنبه‌های اساسی پروتکل HTTP

در این بخش با برخی جنبه‌های اساسی پروتکل HTTP آشنا می‌شویم.

HTTP ساده است

HTTP به طور کلی چنان طراحی شده است که ساده و قابل خواندن از سوی انسان باشد و حتی با وجود پیچیدگی‌هایی که در نسخه HTTP/2 و کپسوله‌سازی پیام‌های HTTP در فریم‌ها انجام یافته، این اصل همچنان رعایت می‌شود. پیام‌های HTTP می‌توانند از سوی انسان خوانده شده و درک شوند و امکان تست آسان برای توسعه‌دهندگان عرضه می‌کند و پیچیدگی‌ها را برای افراد مبتدی کاهش می‌دهد.

HTTP قابل بسط است

هدرهای HTTP که در نسخه HTTP/1.0 معرفی شده‌اند، موجب می‌شوند که بسط این پروتکل و آزمایش کردن آن آسان باشد. کارکردهای جدید می‌توانند حتی با یک توافق ساده بین یک کلاینت و سرور در مورد معناشناسی تازه هدرها، برقرار شوند.

HTTP حالت ندارد، اما نشست دارد

HTTP فاقد «حالت» (State) است، یعنی هیچ پیوندی بین دو درخواست که پشت سر هم روی یک اتصال انتقال می‌یابند، وجود ندارد. این امر موجب می‌شود افرادی که می‌خواهند با صفحه‌های خاصی مانند سبد خرید فروشگاه‌های آنلاین به صورت یکپارچه تعامل پیدا کنند، با مشکل مواجه شوند. اما با این که خود HTTP فاقد حالت است، به لطف کوکی‌های HTTP می‌توان از «نشست‌های باحالت» (Stateful Sessions) استفاده کرد. با بهره‌گیری از خصوصیت بسط‌پذیری هدر، کوکی‌های http به گردش کار اضافه می‌شوند و امکان ایجاد نشست را به هر درخواست HTTP می‌دهند تا چارچوب یکسانی را با حالت مشابه به اشتراک بگذارند.

HTTP و اتصال‌ها

یک «اتصال» (Connection) در لایه انتقال، کنترل می‌شود و از این رو اساساً خارج از دامنه HTTP قرار دارد. با این حال پروتکل HTTP برای این که مبتنی بر اتصال باشد، نیازی به لایه زیربنایی انتقال ندارد، و تنها کافی است که «پایدار» (Reliable) باشد یعنی پیام‌ها را از دست ندهد (یا دست کم خطایی نشان دهد). از میان دو پروتکل نتایج انتقال در اینترنت، TCP پایدار است، اما UDP چنین نیست. از این رو پروتکل HTTP روی استاندارد TCP کار می‌کند که مبتنی بر اتصال است.

پیش از آن که یک کلاینت و سرور بتوانند جفت درخواست/پاسخ HTTP را با هم مبادله کنند، باید یک اتصال TCP برقرار سازند و این فرایند نیازمند چندین رفت و برگشت است. رفتار پیش‌فرض HTTP/1.0 این است که برای هر جفت درخواست/پاسخ HTTP یک اتصال جدید TCP باز کند. این وضعیت در زمان ارسال چنین درخواست به صورت پشت سر هم، کارآیی کمتری نسبت به اشتراک یک TCP منفرد دارد.

برای رفع این نقیصه، HTTP/1.1 مفهوم Pipelining و اتصال‌های مداوم را معرفی کرده است. به این ترتیب اتصال زیربنایی TCP می‌تواند تا حدودی توسط هر Connection کنترل شود. HTTP/2.2 یک گام پا را فراتر گذاشته و پیام‌ها را روی یک اتصال منفرد تقسیم می‌کند و به این ترتیب اتصال TCP بهره‌وری بالاتری پیدا می‌کند.

آزمایش‌هایی در جریان است که یک پروتکل انتقال بهتر ساخته شود که برای HTTP مناسب‌تر باشد. برای نمونه گوگل در حال آزمایش QUIC (+) است که بر مبنای UDP ساخته می‌شود تا پروتکل انتقال پایدارتر و کارآمدتری عرضه کند.

HTTP چه چیزهایی را می‌تواند کنترل کند؟

ماهیت بسط‌پذیر پروتکل HTTP در طی زمان به ما این امکان را داده است که کنترل و کارکردهای بیشتری روی وب داشته باشیم. متدهای کش یا احراز هویت، کارکردهایی هستند که در ابتدا از سوی HTTP مدیریت می‌شدند. به طور عکس توانایی رهایی از قید origin تنها در دهه 2010 میلادی به این پروتکل اضافه شده است. در ادامه فهرستی از قابلیت‌های متداولی را مشاهده می‌کنید که از سوی HTTP کنترل می‌شوند.

کش کردن

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

رهایی از قید Origin

مرورگرهای وب برای جلوگیری از سرقت اطلاعات و دیگر مداخلات در حریم خصوصی کاربران، یک جداسازی الزامی بین وب‌سایت‌ها ایجاد می‌کنند، به این ترتیب تنها صفحه‌هایی با منشأ (Origin) یکسان می‌توانند به همه اطلاعات صفحه وب دسترسی داشته باشند. با این که چنین قیدی یک مزاحمت برای سرور محسوب می‌شود، اما هدرهای HTTP می‌توانند این جداسازی صریح را در سمت سرور آزاد سازند و به سند امکان دهند که یک لحاف چهل تکه از اطلاعات باشد که از دامنه‌های مختلف تأمین می‌شوند. حتی ممکن است برخی دلایل امنیتی برای انجام این کار وجود داشته باشد.

احراز هویت

برخی صفحه‌های وب را می‌توان محافظت کرد، به طوری که تنها کاربران خاصی بتوانند به آن‌ها دسترسی داشته باشند. فرایند ابتدایی احراز هویت می‌تواند از سوی HTTP ارائه شود، که این کار یا از طریق WWW-Authenticate و هدرهای مشابه یا با تعیین یک نشست خاص با استفاده از کوکی‌های HTTP انجام می‌یابد.

پراکسی و تونلینگ

سرورها یا کلاینت‌ها غالباً روی اینترانت قرار دارند و نشانی IP واقعی‌شان را از دیگر رایانه‌ها پنهان می‌کنند. سپس درخواست‌های HTTP از طریق واسطه‌ها عبور می‌کنند تا از این موانع شبکه رد شوند. البته همه پراکسی‌ها، پراکسی‌های HTTP نیستند. برای نمونه پروتکل SOCKS در سطح پایین‌تری عمل می‌کند و پروتکل‌های دیگر مانند FTP نیز می‌توانند از سوی این واسطه‌ها مدیریت شوند.

نشست‌ها

استفاده از کوکی‌های HTTP به شما امکان می‌دهد که درخواست‌های HTTP را به حالت سرور پیوند دهید. با این کار نشست‌ها ایجاد می‌شوند، هر چند که HTTP ابتدایی یک پروتکل بی‌حالت است. این وضعیت نه تنها برای مدیریت سبد خرید فروشگاه‌های آنلاین مفید است، بلکه برای هر سایتی که امکان پیکربندی خروجی خود را به کاربر می‌دهد، مفید خواهد بود.

گردش HTTP

زمانی که یک کلاینت می‌خواهد با یک سرور ارتباط بگیرد، چه یک سرور نهایی و چه پراکسی بی‌درنگ باشد، مراحل زیر را اجرا می‌کند:

  • یک اتصال TCP باز می‌کند: اتصال TCP برای فرستادن یک یا چند درخواست و دریافت یک پاسخ استفاده می‌شود. کلاینت ممکن است یک اتصال جدید باز کند، از اتصال موجود استفاده مجدد نماید، یا چند اتصال TCP را به سرور برقرار سازد.
  • ارسال یک پیام HTTP: پیام‌های HTTP ‌(پیش از HTTP/2) قابل خواندن از سوی انسان هستند. با استفاده از HTTP/2 این پیام‌های ساده در فریم‌ها جاسازی می‌شوند و به این ترتیب دیگر مستقیماً امکان خواندن آن‌ها وجود ندارد، اما اصول کار یکسان است. به مثال زیر توجه کنید:
1GET / HTTP/1.1
2Host: developer.mozilla.org
3Accept-Language: fr
  • خواندن پاسخ ارسالی از سوی سرور: روش کار مانند مثال زیر است:
1HTTP/1.1 200 OK
2Date: Sat, 09 Oct 2010 14:28:02 GMT
3Server: Apache
4Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
5ETag: "51142bc1-7449-479b075b2891b"
6Accept-Ranges: bytes
7Content-Length: 29769
8Content-Type: text/html
9
10<!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
  • بستن یا استفاده مجدد از اتصال برای درخواست‌ها بعدی.

اگر قابلیت pipelining در HTTP فعال باشد، چندین درخواست می‌توانند بدون منتظر ماندن برای دریافت کامل پاسخ اول، ارسال شوند. قابلیت pipelining در HTTP در نسخه HTTP/2 منسوخ شده است، زیرا این نسخه جدید امکان تقسیم (pipelining) درخواست‌ها را درون یک فریم ارائه کرده است، که بسیار پایدارتر است.

پیام‌های HTTP

پیام‌های HTTP آن چنان که در HTTP/1.1 و قبل‌تر تعریف شده‌اند، از سوی انسان قابل خواندن هستند. در HTTP/2 این پیام‌ها در یک ساختار دودویی جاسازی شده‌اند که «فریم» (frame) نامیده می‌شود و امکان بهینه‌سازی‌هایی مانند فشرده‌سازی هدرها و مالتی‌پلکسینگ را فراهم می‌سازد. حتی اگر بخشی از پیام اصلی HTTP در این نسخه از پروتکل ارسال شود، معناشناسی هر پیام بی‌تغییر می‌ماند و کلاینت درخواست اصلی HTTP/1.1 را بازسازی می‌کند. از این رو برای خلاصه‌سازی پیام‌های HTTP/2 در فرمت HTTP/1.1 مفید است.

دو نوع از پیام‌های HTTP وجود دارند که درخواست‌ها و پاسخ‌ها نامیده می‌شوند و هر یک فرمت خاص خود را دارند.

درخواست‌های HTTP

در ادامه نمونه‌ای از یک درخواست HTTP را مشاهده می‌کنید:

پروتکل HTTP

درخواست‌ها شامل اجزای زیر هستند:

  • متد HTTP که معمولاً یک فعل مانند GET، POST یا یک اسم مانند OPTIONS یا HEAD است و عملیاتی را تعریف می‌کند که کلاینت می‌خواهد اجرا کند. به طور معمول، کلاینت می‌خواهد یک منبع را (با استفاده از GET) واکشی کند یا مقدار یک فرم HTML را (با استفاده از POST) ارسال کند، هر چند عملیات زیاد دیگری نیز در موقعیت‌های دیگر مورد نیاز هستند.
  • هدف درخواست که به طور معمول یک URL یا مسیر مطلق پروتکل، پورت و دامنه است و بر اساس کانتکست درخواست مشخص می‌شود. قالب‌بندی این «هدف درخواست» بر اساس متدهای مختلف HTTP متفاوت است.
  • نسخه پروتکل HTTP.
  • هدرهای اختیاری که اطلاعات اضافی را به سرورها انتقال می‌دهند.
  • همچنین ممکن است یک body وجود داشته باشد که برای برخی متدها مانند POST مشابه موارد پاسخ است که شامل منبع ارسالی هستند.

پاسخ‌های HTTP

در این بخش ابتدا مثالی از یک پاسخ HTTP را مشاهده می‌کنید:

پروتکل HTTP

پاسخ‌ها شامل اجزای زیر هستند:

  • نسخه پروتکل HTTP که استفاده شده است.
  • «کد وضعیت» (Status Code) که نشان می‌دهد آیا درخواست موفق بوده یا نه و دلیل آن چیست.
  • یک پیام وضعیت که توضیح کوتاه غیر قابل استناد در مورد کد وضعیت است.
  • هدرهای HTTP مانند مواردی که در خصوص درخواست HTTP برشمردیم.
  • همچنین به صورت اختیاری می‌تواند شامل یک body باشد که شامل منبع واکشی شده است.

API-های مبتنی بر HTTP

پراستفاده‌ترین API مبتنی بر HTTP یک API به نام XMLHttpRequest است که می‌تواند برای مبادله داده‌ها بین یک عامل کاربر و سرور استفاده شود. Fetch API مدرن همین قابلیت‌ها را با مجموعه امکانات قدرتمندتر و منعطف‌تر عرضه می‌کند.

API دیگر رویدادهای ارسالی از سمت سرور هستند که یک سرویس یک‌طرفه هستند که به سرور امکان می‌دهند تا رویدادها را به کلاینت ارسال کند و از HTTP به عنوان یک سازوکار انتقالی بهره بگیرد. کلاینت با استفاده از اینترفیس EventSource یک اتصال باز کرده و دستگیره‌های رویداد را ایجاد می‌کند. مرورگر کلاینت به طور خودکار، پیام‌هایی را که روی استریم HTTP به اشیای مناسب Event می‌رسند، تبدیل می‌کند و آن‌ها را به دستگیره‌های رویدادی تحویل می‌دهد که برای آن نوع (type) رویداد ثبت شده‌اند و یا اگر دستگیره رویدادی برای آن نوع خاص تعیین نشده باشید، به دستگیره رویداد onmessage تحویل می‌دهد.

سخن پایانی

HTTP یک پروتکل بسط‌‌پذیر است که استفاده آسانی دارد. ساختار کلاینت-سرور در ترکیب با امکان افزودن ساده هدرها به پروتکل HTTP امکان می‌دهد که همراه با گسترش ظرفیت‌های وب، توسعه یابد. با این که HTTP/2 برخی پیچیدگی‌ها را وارد این پروتکل کرده است، اما با جاسازی پیام‌های HTTP در فریم‌ها موجب بهبود عملکرد شده است. ساختار ابتدایی پیام‌ها از نسخه HTTP/1.0 همچنان یکسان باقی مانده است. گردش نشست نیز ساده است و امکان بررسی و دیباگ با استفاده از message monitor را در اختیار ما قرار می‌دهد.

بر اساس رای ۲۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
developer.mozilladeveloper.mozilla
۲ دیدگاه برای «پروتکل HTTP چیست؟ — به زبان ساده»

“مسیر منبع برای واکشی که URL منبع جدا شده از عناصری است که از روی چارچوب روشن است”
آخه این چه ترجمه ایه!

سلام و وقت بخیر دوست عزیز؛
اشکال موجود در بخشی از متن که اشاره فرموده بودید، اصلاح شد.
از تذکر به‌جای شما سپاسگزاریم

نظر شما چیست؟

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