اگه تا حالا برای پیاده‌سازی یک جستجوی پیچیده مجبور شدید بین GET و POST یکی رو انتخاب کنید و از هیچ‌کدوم راضی نبودید، خبر خوبی براتون دارم. در ژوئن ۲۰۲۶ (خرداد ۱۴۰۵)، IETF سند RFC 10008 رو منتشر کرد که یه متد کاملاً جدید به اسم QUERY رو به HTTP اضافه می‌کنه. نویسنده‌های این سند جولیان رشکی، جیمز اسنل و مارک بیشاپ هستن.

توی این پست بررسی می‌کنیم متد QUERY چیه و چه مشکلی رو حل می‌کنه.

مشکل قدیمی: GET یا POST؟

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

  1. محدودیت‌های متد GET:
    • طول URI: اگر حجم داده‌های جستجو شده زیاد بود، از محدوده‌ی مجاز طول URL بیشتر می‌شد.
    • امنیت و حریم خصوصی: پارامترهای جستجو در URL نمایش داده می‌شدند که باعث می‌شد توی لاگ‌های سرور، تاریخچه مرورگر و بوک‌مارک‌ها ثبت بشن.
    • پیچیدگی انکودینگ: تبدیل داده‌های پیچیده به فرمت قابل فهم برای URL بسیار ناکارآمد بود.
  2. محدودیت‌های متد POST:
    • عدم شفافیت در تکرارپذیری: متد POST ذاتاً امن (Safe) یا تکرارپذیر (Idempotent) تعریف نشده است.
    • مشکلات کشینگ: پاسخ‌های متد POST به راحتی قابل کش (Cache) شدن نیستند.

    نتیجه؟ سال‌هاست که توسعه‌دهنده‌ها مجبور بودن یا فیلترهای پیچیده‌ی جستجو رو توی URL بچپونن (مثل نمونه‌ی زیر) یا از POST برای عملیات صرفاً خوندنی (Read-only) سوءاستفاده کنن و مزایای کشینگ و تکرار پذیری رو از دست بدن.

    GET /products?category=running&price_min=50
    &price_max=200&color=red&color=blue
    &sort=rating&in_stock=true...

    متد QUERY وارد می‌شود!

    متد QUERY طراحی شده تا بهترین ویژگی‌های هر دو متد را ترکیب کنه. این متد مثل GET امن (Safe) و تکرارپذیر (Idempotent) هست، به این معنی که اجرای اون تغییری توی وضعیت سرور ایجاد نمی‌کنه و در صورت قطع اتصال، می‌توان اون رو بدون نگرانی دوباره ارسال کرد. از طرف دیگه، مثل متد POST این امکان رو به شما میده تا پارامترهای جستجو رو به جای URL توی بدنه‌ی درخواست (Request Body) قرار بدید.

    QUERY /products HTTP/1.1
    Content-Type: application/json
     
    {
      "category": "running",
      "price": { "min": 50, "max": 200 },
      "sort": "rating"
    }

    ویژگی‌های کلیدی QUERY

    • امنیت بالا: از اونجایی که اطلاعات توی Request Body ارسال می‌شن، دیگه توی لاگ‌های URI سیستم‌های واسط نمایش داده نمی‌شن.
    • قابلیت کشینگ (Caching): برخلافPOST، پاسخ‌های متد QUERY کاملاً قابل کش شدن هستن. سرورها می‌تونن بر اساس محتوای درخواست و متادیتای اون، یک کلید کش (Cache Key) ایجاد کنن.
    • هدر Accept-Query: این هدر جدید به کلاینت اجازه میده تا متوجه بشه سرور از چه فرمت‌هایی (مثل JSONPath یا SQL) برای پرس‌وجو پشتیبانی می‌کنه.
    • درخواست‌های مشروط (Conditional Requests): متد QUERY از هدرهای مشروط (مثل If-None-Match) پشتیبانی می‌کند تا در صورتی که نتایج تغییر نکرده باشن، از ارسال مجدد داده‌های تکراری جلوگیری بشه.
    • منابع معادل (Equivalent Resource): یکی از جالب‌ترین بخش‌های RFC 10008 اینه که سرور می‌تونه به نتیجه‌ی یک QUERY، یک URI اختصاص بده. با این کار، کلاینت می‌تونه توی دفعات بعدی به جای ارسال مجدد کل بدنه جستجو، از یک متد ساده‌ی GET برای دریافت همون نتایج استفاده کنه.

    آیا همین حالا باید سراغش بریم؟

    نه، حداقل نه همین الآن. چند تا نکته رو در نظر بگیرید:

    • پشتیبانی از QUERY هنوز توی مرورگرها، پراکسی‌ها و API Gatewayها محدوده و ممکنه سال‌ها طول بکشه تا همه جا در دسترس باشه.
    • زیرساخت‌های قدیمی‌تر ممکنه متدهای HTTP ناآشنا رو کلاً رد کنن.
    • اگه کاربرها باید بتونن لینک‌ها رو به اشتراک بذارن یا بوکمارک کنن، همچنان از GET استفاده کنید؛ چون درخواست‌های QUERY رو نمیشه به‌صورت لینک به اشتراک گذاشت.
    • پیاده‌سازی کش سفارشی برای QUERY هم پیچیده‌تر از GET هست، چون باید بدنه‌ی درخواست رو هم در نظر بگیرید.

    در واقع QUERY قرار نیست جایگزین GET بشه بلکه جایگزین سوءاستفاده از POST برای عملیات‌های خوندنیه. مسیر پذیرش QUERY احتمالاً شبیه متد PATCH خواهد بود که استانداردش سال‌ها پیش نوشته شد، ولی پذیرش گسترده‌ی اون زمان بیشتری برد.

    حرف آخر

    RFC 10008 با متد QUERY راهی امن، تکرار پذیر و قابل کش شدن برای ارسال یک Request Body، بدون گیر افتادن توی محدودیت‌های URL و بدون از دست دادن مزایای متدهای Safe ایجاد می‌کنه. برای APIهای داخلی، سرویس‌های جستجو و فیلترهای پیچیده، QUERY گزینه‌ی خیلی مناسب‌تری نسبت به POST سنتیه؛ ولی برای پذیرش گسترده توی محیط‌های عملیاتی، هنوز باید صبر کرد.

    اگه توی پروژه‌های خودتون با Endpointهای جستجو یا فیلترینگ سنگین سروکار دارید، وقتشه که متد QUERY رو زیر نظر داشته باشید.