بررسی متدهای PUT و PATCH در REST API

PUT و PATCH در REST API

در طراحی RESTful API، دو روش HTTP به نامهای PUT و PATCH هستند که برای به‌روزرسانی منابع (resources) روی سرور مورد استفاده قرار می‌گیرند، اما تفاوت بین PUT و PATCH در REST API در نحوه انجام به‌روزرسانی‌ها و سناریوهایی است که هر کدام مناسب‌تر هستند. هر دو متد برای اصلاح داده‌های موجود طراحی شده‌اند، اما درک تفاوت PUT و PATCH در REST API می‌تواند به توسعه‌دهندگان کمک کند تا بهترین انتخاب را بر اساس ماهیت به‌روزرسانی که باید انجام دهند، انجام دهند. در این مطلب ، تفاوت PUT و PATCH در REST API را بررسی خواهیم کرد.

PUT در REST API چیست؟

برای درک تفاوت بین PUT و PATCH در REST API، ابتدا باید بدانیم PUT چیست. متد PUT در REST API درخواست می‌کند که موجودیت محصور شده در Request-URI ارائه شده ذخیره شود. اگر Request-URI به یک منبع از قبل موجود اشاره دارد، موجودیت محصور شده باید به عنوان نسخه اصلاح شده موجود در سرور مبدا در نظر گرفته شود. اگر Request-URI به یک منبع موجود اشاره نکند و URI بتواند به عنوان یک منبع جدید توسط عامل کاربر درخواست کننده تعریف شود، سرور مبدا می‌تواند منبع را با آن URI ایجاد کند.

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

 

بنابراین، PUT برای موارد استفاده زیر بهترین است:

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

در سیستم‌هایی مانند Elasticsearch، عملیات idempotent برای تضمین سازگاری داده‌ها ضروری است. به عنوان مثال، به روز رسانی یک سند در Elasticsearch با استفاده از PUT تضمین می‌کند که همان درخواست می‌تواند بدون عوارض جانبی ناخواسته تکرار شود.

 

PATCH در REST API چیست؟

اکنون که PUT در REST APIها را بررسی کردیم، قبل از مقایسه PUT و PATCH در REST API، نگاهی به PATCH و نحوه عملکرد آن بیندازیم.  متد PATCH در REST API درخواست می‌کند که مجموعه ای از تغییرات توصیف شده در موجودیت درخواست در منبع شناسایی شده توسط Request-URI اعمال شود.

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

 

به همین دلیل است که متد PATCH در REST API برای موارد استفاده زیر مناسب تر است:

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

برای پلتفرم‌هایی مانند headless CMS که اغلب ساختارهای محتوای پیچیده را مدیریت می‌کنند، استفاده از PATCH برای به‌روزرسانی‌های کوچک‌تر – مانند اصلاح یک فیلد واحد – می‌تواند لود سرور را کاهش و عملکرد را بهبود بخشد.

قبل از اینکه به تفاوت بین PUT و PATCH در REST API بپردازیم، باید در مورد Idempotence در این دو روش صحبت کنیم.

 

منظور از Idempotence در متدهای PUT  و PATCH

در REST APIها، idempotence به خاصیت عملیاتی اطلاق می شود که با تکرار چندین بار با ورودی‌های یکسان، نتیجه یکسانی را به همراه دارد. به این معنی که چندین بار درخواست یکسان باید تاثیر یکسانی روی سرور داشته باشد، صرف نظر از اینکه چند بار اجرا شده است. این برای اطمینان از ثبات و قابل پیش بینی بودن در API مهم است. اما چگونه به تفاوت PUT و PATCH در REST API مرتبط است؟

 

متد PUT و Idempotence

متد PUT در REST API همیشه idempotent است زیرا برای جایگزینی کل منبع در یک URI مشخص با دادههای ارائه شده در درخواست طراحی شده است. به عبارت دیگر، اگر یک درخواست PUT را چندین بار با داده های منبع یکسان انجام دهید، نتیجه همیشه یکسان خواهد بود.

وقتی درخواست PUT میکنید، در اصل به سرور می‌گویید: «این وضعیت کامل و دقیقی است که من برای این منبع می‌خواهم.» چه درخواست PUT را یک بار یا چند بار صادر کنید، منبع حاصل همیشه یکسان خواهد بود.

به عنوان مثال، سناریویی را در نظر بگیرید که در آن آدرس ایمیل یک کاربر را به روز می‌کنید. اگر یک درخواست PUT را چندین بار انجام دهید، نتیجه تغییر نخواهد کرد زیرا هر بار منبع با همان داده جایگزین می‌شود.

مثال:

PUT /users/1{“username”: “hasm”,”email”: “hasm@example.com”}

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

{“username”: “hasm”,”email”: “hasm@example.com”}

حتی اگر داده های کاربر از قبل این باشد، ارسال مجدد درخواست چیزی را تغییر نمی‌دهد. داده‌ها را با همان داده‌ها جایگزین می‌کند، بنابراین تاثیر درخواست بدون در نظر گرفتن چند بار تکرار یکسان باقی می‌ماند. این چیزی است که PUT را idempotent می‌کند.

 

متد PATCH و Idempotence

متد PATCH در REST API، از طرف دیگر، به طور کلی نیز idempotent است، اما با انعطاف پذیری بیشتری. هنگام ایجاد وصله‌ها، مطمئن شوید که عملیات‌ها idempotent هستند (مثلا تعیین مقدار) تا از عوارض جانبی ناخواسته درخواست‌های مکرر جلوگیری کنید. این که PATCH واقعا idempotent است یا خیر، به عملیات و داده‌های در حال تغییر بستگی دارد.

برای درخواست‌های PATCH عبارت idempotence، به این معنی است که چندین بار اعمال یک patch یکسان نتیجه یکسانی خواهد داشت. این تا زمانی درست است که خود patch در صورت اعمال مکرر عوارض جانبی یا تغییرات اضافی ایجاد نکند. اگر همچنان همان patch را با همان داده ها اعمال می کنید، نتیجه باید پس از اولین برنامه بدون تغییر باشد.

به عنوان مثال، اگر فقط ایمیل یک کاربر را به روز می کنید، ارسال مکرر همان درخواست PATCH نتیجه را بعد از اولین بار تغییر نمی دهد، حتی اگر درخواست چندین بار انجام شود. ایمیل کاربر یکسان خواهد ماند و وضعیت منبع تغییر نخواهد کرد.

 

PATCH API مثال:

PATCH /users/1{“email”: “hasm@newdomain.com”}

اگر ایمیل قبلا hasm@newdomain.com بود، اعمال مجدد این patch منجر به تغییری نمی‌شود و آن را idempotent می‌کند.

با این حال، PATCH همچنین می تواند در برخی موارد غیرقابل نفوذ باشد. به عنوان مثال، اگر یک عملیات PATCH یک شمارنده را تغییر دهد یا مواردی را به یک لیست اضافه کند (مانند افزایش یک عدد یا الحاق به یک آرایه)، استفاده های مکرر از همان PATCH می تواند به نتایج متفاوتی منجر شود. این باعث نقض خاصیت idempotence می‌شود.

 

نمونه API REST PATCH غیر idempotent:

PATCH /counter/1{“increment”: ۱}

اگر این patch را مدام اعمال کنید، شمارنده همچنان افزایش می‌یابد و در نتیجه هر بار مقادیر متفاوتی به دست می‌آید. این idempotent نیست زیرا نتیجه با هر برنامه تغییر می‌کند.

خرید vps لینوکس یک ماشین مجازی کامل است که امکان دسترسی SSH طبق آموزش را به آن خواهید داشت.
خرید vps لینوکس در پنج موقعیت جغرافیایی ایران، ترکیه، هلند، آلمان و آمریکا با قابلیت تحویل آنی در پارسدو فراهم است.

سناریوهای مثال PUT و PATCH در REST API

بیایید با مثال‌هایی به تفاوت بین PUT و PATCH نگاه کنیم، از جمله عملیات idempotent و non-idempotent.

 

سناریو ۱: درخواست PUT – جایگزینی یک منبع کامل

یک نقطه پایانی API را برای مدیریت محصولات در یک سیستم تجارت الکترونیک تصور کنید. شما باید تمام جزئیات یک محصول از جمله نام، قیمت و توضیحات آن را به روز کنید. این یک مثال معمولی از متد PUT و PATCH در HTTP است، که در آن PUT برای جایگزینی منبع کامل محصول استفاده می‌شود.

 

محصول اولیه:

GET /products/1001{“id”: ۱۰۰۱,”name”: “Laptop”,”price”: ۹۹۹.۹۹,”description”: “A powerful laptop.”}

می خواهید قیمت و توضیحات محصول را به روز کنید. شما یک درخواست PUT با کل منبع ارسال می کنید:

درخواست PUT:

PUT /products/1001{“id”: ۱۰۰۱,”name”: “Laptop”,”price”: ۸۹۹.۹۹,”description”: “A discounted powerful laptop.”}

اگر این درخواست PUT را یک یا چند بار انجام دهید، نتیجه همیشه یکسان خواهد بود. جزئیات محصول به روز می شود تا قیمت و توضیحات جدید را منعکس کند و هر بار نتیجه یکسانی رخ خواهد داد که ماهیت idempotent متد PUT را تضمین می‌کند.

نتیجه (پس از درخواست PUT):

{“id”: ۱۰۰۱,”name”: “Laptop”,”price”: ۸۹۹.۹۹,”description”: “A discounted powerful laptop.”}

سناریو ۲: درخواست PATCH- به روز رسانی بخشی از یک منبع

اکنون، اجازه دهید درخواست PATCH را برای به‌روزرسانی تنها بخشی از جزئیات محصول، مانند توضیحات، در نظر بگیریم. مثال PATCH API: اگر می خواهید توضیحات محصول را تغییر دهید اما قیمت آن تغییر نکند، PATCH انتخاب بهتری است. برای پیاده سازی این، باید patchهایی ایجاد کنید که فقط حاوی فیلدهایی هستند که نیاز به اصلاح دارند، مانند توضیحات در این مثال API REST PATCH.

محصول اولیه:

GET /products/1001{“id”: ۱۰۰۱,”name”: “Laptop”,”price”: ۹۹۹.۹۹,”description”: “A powerful laptop.”}

درخواست patch :

PATCH /products/1001{“description”: “A lightweight, powerful laptop.”}

وقتی این درخواست PATCH را ارسال می‌کنید، فقط قسمت توضیحات به روز می‌شود. اگر یک درخواست PATCH را چندین بار ارسال کنید، توضیحات پس از اولین به‌روزرسانی بدون تغییر باقی می‌ماند و درخواست را idempotent می‌کند.

 

نتیجه (بعد از درخواست patch ):

{“id”: ۱۰۰۱,”name”: “Laptop”,”price”: ۹۹۹.۹۹,”description”: “A lightweight, powerful laptop.”}

اگر دوباره همان patch را اعمال کنید، توضیحات محصول همچنان همان چیزی است که بعد از اولین patch بود. نتیجه سازگار است، که باعث می‌شود PATCH در این سناریو idempotent باشد.

سناریو ۳: درخواست PATCH- عملیات Non-idempotent

بیایید به یک عملیات پچ non-idempotent نگاه کنیم. فرض کنید یک نقطه پایانی برای موجودی کیف پول یک کاربر وجود دارد و شما می‌خواهید موجودی را افزایش دهید. یک مثال تفاوت بین PUT و PATCH را می توان در اینجا نشان داد: PATCH هر بار مقداری به موجودی اضافه می کند.

کیف پول اولیه:

GET /users/1/wallet{“id”: ۱,”balance”: ۱۰۰.۰۰}

درخواست پچ:

PATCH /users/1/wallet{“increment”: ۵۰.۰۰}

این درخواست PATCH موجودی کیف پول را ۵۰ دلار افزایش می‌دهد. اگر این درخواست patch را چندین بار ارسال کنید، موجودی با هر patch افزایش می‌یابد و هر بار به نتیجه متفاوتی منجر می‌شود. این non-idempotent است، زیرا استفاده مکرر از همان PATCH نتیجه متفاوتی را در پی خواهد داشت.

نتیجه (پس از اولین درخواست patch ):

{“id”: ۱,”balance”: ۱۵۰.۰۰}

نتیجه (پس از دومین درخواست patch ):

{“id”: ۱,”balance”: ۲۰۰.۰۰}

در این مثال پچ idempotent نیست زیرا درخواست‌های مکرر با داده‌های یکسان نتایج متفاوتی ایجاد می‌کنند.

تفاوت های کلیدی بین PUT و PATCH در REST API

تفاوت اصلی بین PUT و PATCH در REST API این است که چگونه به روز رسانی‌ها را مدیریت می‌کنند. PUT جایگزین کل ریسورس می‌شود، بنابراین هر قسمت از دست رفته پاک شده، که می‌تواند منجر به از دست رفتن داده شود. به همین دلیل است که توسعه‌دهندگان patchهایی برای به‌روزرسانی‌های جزئی ایجاد می‌کنند تا از بازنویسی فیلدهای بدون تغییر جلوگیری و یکپارچگی داده‌ها را حفظ کنند.

این باعث می شود PATCH برای به روز رسانی‌های جزئی کارآمدتر شود. یک مثال PATCH API این است که اگر می‌خواهید فقط ایمیل یک کاربر را به‌روزرسانی کنید، ایجاد patch فقط فیلد ایمیل را ارسال می‌کند، برخلاف درخواست PUT که به کل اطلاعات کاربر نیاز دارد.

با PUT، محموله کامل داده مورد نیاز است یعنی هر فیلد باید ارسال شود و هر فیلد از دست رفته پاک خواهد شد. با این حال، PATCH فقط فیلدهایی را ارسال می‌کند که باید به روز شوند و کارآمدتر می شود، به خصوص برای منابع بزرگ با حداقل تغییرات. روش PATCH در REST API اجازه می دهد تا درخواست های متمرکزتر و کوچکتر را انجام دهید و انتقال داده ها را کاهش می دهد.

هر دو متد PUT و PATCH دارای ویژگی idempotent هستند یعنی  تکرار همان درخواست منجر به یک نتیجه می‌شود. با این حال، PUT قابل پیش بینی تر است زیرا جایگزین کل ریسورس می‌شود. PATCH، زمانی که فقط برای اصلاح فیلدهای مشخص شده استفاده می‌شود، بسته به نحوه مدیریت به‌روزرسانی‌ها توسط سرور، ممکن است به نتایج متفاوتی منجر شود.

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

در نتیجه، تفاوت PUT و PATCH در REST API به ماهیت به‌روزرسانی‌ها خلاصه می‌شود؛ PATCH برای تغییرات جزئی است، در حالی که PUT برای جایگزینی کامل منابع است. هر دو idempotent هستند، اما PATCH می تواند پیچیده‌تر باشد.

 

جمع بندی

هر دو PUT و PATCH متدهای HTTP اساسی در طراحی REST API هستند، اما اهداف متفاوتی را دنبال می‌کنند، که ماهیت تفاوت PUT و PATCH در REST API است. شما می‌توانید با درک تفاوت بین PUT و PATCH با مثال هایی که قبلا در این مطلب به آن پرداختیم، کارایی، وضوح و عملکرد API خود را به میزان قابل توجهی بهبود بخشید. همیشه ماهیت به‌روزرسانی – خواه کامل یا جزئی – به همراه تاثیر بر عملکرد و یکپارچگی داده‌ها را در نظر بگیرید و متدی را انتخاب کنید که به بهترین وجه با نیازهای شما مطابقت دارد.