توی دنیای توسعه نرمافزار، یکی از بزرگترین چالشها اینه که چطور سیستمهای مختلف، با معماریها و زبانهای برنامهنویسی متفاوت، بتونن با هم ارتباط برقرار کنن و داده رد و بدل کنن. معماری REST API همون راهکاریه که این مشکل رو به بهترین شکل ممکن حل کرده. توی این مقاله قراره مفاهیم پایه و مهندسی REST API رو با مثالهای واقعی بررسی کنیم.
کلمه API مخفف Application Programming Interface یا «رابط برنامهنویسی اپلیکیشن» هست. از دیدگاه مهندسی نرمافزار، API یه قرارداد و واسطه است که اجازه میده دو تا سیستم کاملاً مجزا (مثلاً یه اپلیکیشن موبایل و یه دیتابیس ابری) بتونن با هم تبادل داده داشته باشن.
API چه مشکلی را حل میکند؟ اگه API نبود، یکپارچهسازی سیستمها به شدت سخت، ناامن و مستعد خطا میشد. برای مثال، وقتی یک سیستم حسابداری سازمانی میخواد اطلاعات تراکنشها رو به یک درگاه پرداخت بانکی بفرسته، مستقیماً به دیتابیس بانک وصل نمیشه؛ بلکه از طریق API بانک، درخواستش رو ارسال میکنه.
نقش Server و Client: این ارتباط همیشه بین دو تا نقش اصلی شکل میگیره:
کلاینت (Client): درخواستکننده اطلاعاته؛ مثل مرورگر سیستم شما، یک اپلیکیشن موبایل، یا حتی یک سرور دیگه که داره سرویسی رو فراخوانی میکنه.
سرور (Server): سیستمیه که این درخواست رو دریافت میکنه، لاجیک (منطق) تجاری رو روش پیادهسازی میکنه و جواب رو برمیگردونه.
وقتی این تبادل داده روی بستر اینترنت و با استفاده از پروتکل استاندارد HTTP انجام بشه، بهش Web API میگیم.
ارتباط Client و Server از طریق HTTP: در Web API، کلاینت و سرور برای اینکه حرف هم رو بفهمن، از قوانین و بستر شبکه HTTP استفاده میکنن.
مفهوم Request و Response: کل این پروسه تو قالب دو بخش اصلی مدیریت میشه:
درخواست (Request): پیامی که کلاینت برای سرور میفرسته و ازش دیتایی میخواد یا میخواد عملیاتی انجام بشه.
پاسخ (Response): جوابی که سرور بعد از پردازش درخواست، به کلاینت برمیگردونه.
کلمه REST مخفف Representational State Transfer هست. REST یه زبان برنامهنویسی یا لایبرری نیست؛ بلکه یه «سبک معماری» (Architectural Style) و یه سری استاندارده که کمک میکنه Web APIهای مقیاسپذیر (Scalable) و تمیزی بسازیم.
دو تا اصل مهم توی این معماری وجود داره:
مفهوم منبع (Resource): توی دنیای REST، به همه موجودیتها و دادهها به چشم یه «منبع» نگاه میشه. مثلاً توی یه پلتفرم فروش خودرو، هر «ماشین» یه Resource به حساب میاد که میشه اطلاعاتش رو خوند، ماشین جدیدی تعریف کرد، ویرایشش کرد یا از سیستم حذفش کرد.
ویژگی بدون حالت بودن (Stateless): معماری REST کاملاً Stateless یا بدون حالت عمل میکنه. این یعنی سرور هیچ وضعیتی (State) از درخواستهای قبلی کلاینت رو تو مموری خودش ذخیره نمیکنه. هر درخواستی که سمت سرور میفرستیم، باید دقیقاً شامل تمام اطلاعات و توکنهای هویتی لازم برای پردازش باشه. این ویژگی باعث میشه سرورها بتونن میلیونها درخواست رو به صورت همزمان و مستقل پردازش کنن.
تو مهندسی داده، ۴ تا عملیات اصلی داریم که بهشون CRUD (مخفف Create, Read, Update, Delete) میگن. معماری REST این عملیاتها رو روی متدهای استاندارد HTTP مپ (Map) میکنه:
متد GET (معادل Read): برای گرفتن و خوندن اطلاعات از سرور استفاده میشه. این متد نباید هیچ تغییری تو دیتابیس ایجاد کنه.
متد POST (معادل Create): برای فرستادن دادههای جدید (Payload) و ایجاد یه Resource جدید تو سیستم. (مثلاً ثبت یک کاربر جدید).
متد PUT (معادل Update): برای جایگزینی کامل اطلاعات یه منبع موجود. اگر فیلدی رو تو درخواست نفرستید، سرور اون رو با مقادیر خالی (Null) جایگزین میکنه.
متد PATCH (معادل Update جزئی): برای وقتایی که میخوایم فقط یه بخش خاص از اطلاعات رو تغییر بدیم (مثلاً فقط آپدیت کردن قیمت یک ماشین، بدون تغییر نام اون).
متد DELETE (معادل Delete): برای پاک کردن دائمی یا منطقی (Soft Delete) یه منبع از سیستم.
سرور بعد از پردازش درخواست، تو پاسخ خودش یه کد وضعیت ۳ رقمی به کلاینت برمیگردونه تا وضعیت نهایی عملیات رو مشخص کنه. پرکاربردترینِ این کدها به دستههای زیر تقسیم میشن:
200 (OK): درخواست با موفقیت انجام شد و دیتای مورد نظر برگشت داده شد.
201 (Created): داده جدید با موفقیت روی سرور ثبت شد (معمولاً در جواب POST اتفاق میافته).
204 (No Content): عملیات موفقیتآمیز بود، اما سرور دیتایی تو Body برای نمایش نداره (خیلی اوقات بعد از DELETE این کد رو میبینیم).
400 (Bad Request): ساختار درخواستی (مثلاً فرمت JSON) که کلاینت فرستاده اشتباهه (Validation Error).
401 (Unauthorized): کلاینت برای دسترسی نیاز به توکن احراز هویت داره و هنوز لاگین نکرده.
403 (Forbidden): کلاینت لاگین کرده و شناختهشده است، اما سطح دسترسی (Role) لازم برای این عملیات رو نداره.
404 (Not Found): منبع درخواستی روی سرور پیدا نشد.
500 (Internal Server Error): یه باگ یا خطای هندلنشده تو کدهای سمت سرور یا دیتابیس رخ داده.
هر درخواستی که میفرستیم و هر پاسخی که میگیریم، از دو بخش اصلی تشکیل شده است: متا دیتا Header (که شامل اطلاعات جانبی، توکنها و نوع دادههاست) و بدنه اصلی دادهها Body (که اصلِ دادههای در حال انتقال در آن قرار داره)
فرض کنید تو یه سیستم فروش خودرو، کلاینت میخواد اطلاعات ماشینی که شناسهاش 1 هست رو بگیره:
ساختار Request (درخواست):
HTTP
GET /api/cars/10 HTTP/1.1 Host: api.dealership.com Accept: application/json
(در اینجا درخواست به مسیر /api/cars/10 ارسال شده است).
ساختار Response (پاسخ): سرور اطلاعات رو از دیتابیس میخونه و تو فرمت استاندارد و سبک JSON برمیگردونه:
HTTP
HTTP/1.1 200 OK Content-Type: application/json { "id": 10, "name": "شاهین", "price": 850000000 }
(همانطور که میبینید، دیتای ماشین شاهین با قیمت 850,000,000 برگردانده شده است).
طراحی Endpointها یا همون آدرسهای API، یکی از مهمترین بخشهای ساخت یک سیستم استاندارده. بیاید تفاوت این دو تا آدرس رو با هم بررسی کنیم:
/api/cars
/api/getCars
کدوم آدرس اصولیتره؟ آدرس اول (/api/cars) کاملاً درست و استاندارده. تو معماری REST، آدرسها باید فقط شامل «اسمها» (Noun) باشن و نباید هیچ «فعلی» (Verb) توی URL قرار بگیره. دلیل مهندسیِ این قضیه اینه که متدهای HTTP (مثل GET یا POST) خودشون بیانگر عملیات هستن؛ پس اضافه کردن کلمهای مثل get تو آدرس، تکرار مکرراته و باعث میشه API از حالت RESTful خارج بشه.
همچنین اگه بخوایم به منابع مرتبط (Nested Resources) دسترسی پیدا کنیم، ساختار سلسلهمراتبی بهترین انتخابه. مثلاً برای دیدن نظرات ثبتشده برای ماشین شماره ۱۰، آدرسِ /api/cars/10/reviews یک طراحی مناسب و خوانا محسوب میشه.
جمعبندی نهایی
معماری REST صرفاً یه سری قانون خشک نیست؛ بلکه یه توافق جهانی بین برنامهنویسهاست. پیادهسازی درست اصول REST API باعث میشه بکاندی که مینویسیم مقیاسپذیرتر باشه، کلاینتها (چه وب و چه موبایل) خیلی راحتتر بتونن باهاش ادغام بشن، و سیستم در بلندمدت برای تیم توسعه به راحتی قابل نگهداری (Maintainable) باشه.