مفهوم و درک عمیق RESTful Api

مقدمه:سلام و عرض ادب خدمت همه عاشقای دنیای کامپیوتر ها امیدوارم حالتون عالی باشه.اگر در حال خوندن این مطلب هستید، احتمالاً اصطلاحات API و REST رو شنیدید وتعجب کردید که این دیگه چه غول بی شاخ و دمیه!!!!!!!. شاید قبلاً یکم راجع بهش میدونستید، اما نمیدونید واقعا مفهومش چیه و چجوری پیاده سازیش کنید. در این مقاله جادویی، من اصول اولیه REST و نحوه شروع ساخت یک API (از جمله احراز هویت) برای برنامه خودتون رو توضیح خواهم داد.پس تا آخر این مقاله برید جلو که این جادوییترین مقاله در مورد "RESTful Api" هستش.?RESTful APIآخر این مقاله یاد میگیرین : خود API چیه؟؟؟حالا REST چیه؟؟؟متدهای HTTP چیا هستن؟؟؟مثالی از REST رو میبینید.آناتومی REST URL ها رو میشناسیدیاد میگیرید منابع یا Resource های تو در تو چجورین؟؟؟و راه بهتر پیاده سازیشون چیه؟؟؟کدهای وضعیت HTTP چیا هستن و چرا برای REST مهم هستند؟؟؟فرمتهای پاسخ دهی یک API چی هستن و بهترینشون کدومه؟؟؟ساخت یک RESTful API سادهاحراز هویت در APIها به چه شکل است؟؟؟خود API چیه؟؟؟واژه API مخفف عبارت Application Programming Interface(رابط ارتباطات میان برنامه ای) است. این اصطلاح می تونه برای توصیف امکاناتی که یک کتابخانه ارائه میده یا نحوه تعامل با اون استفاده بشه (مثلا متدها یا فانکشنهایی که به ما ارائه میده) کتابخانه مورد علاقه شما ممکنه دارای "API Documentation" باشه که داخلش تمامی امکاناتی که اون کتابخونه به شما ارائه میده و اینکه چجوری اون توابع رو فراخوانی کنین و چه آرگومان هایی برای اجراشون مورد نیاز و غیره رو توضیح میده.با این حال، این روزها، زمانی که مردم به یک API مراجعه می کنن، به احتمال زیاد به یک API HTTP اشاره می کنن، که می تونه راهی برای به اشتراک گذاری داده های برنامه از طریق اینترنت باشه. به عنوان مثال، توییتر یک API داره که به شما این امکان رو میده که توییت‌هایی رو در قالبی درخواست کنین که وارد کردن اون داده ها به برنامه شخصی شما آسون باشه. این قدرت واقعی APIهای HTTP است، که می‌تونن داده‌ها را از چندین برنامه بگیرن و در یک برنامه ترکیب کنن.برای مثال، فرض کنین برنامه‌ای داریم که به شما امکان می‌ده ویجت‌هایی رو مشاهده، ایجاد، ویرایش و حذف کنین. ما می تونیم یک API HTTP ایجاد کنیم که به شما امکان می ده این عملیات رو انجام بدید:http://example.com/view_widgets http://example.com/create_new_widget?name=Widgetizer http://example.com/update_widget?id=123&name=Foo http://example.com/delete_widget?id=123زمانی که همه شروع به پیاده سازی API های خود می کنن، مشکل تازه شروع میشه. بدون یک راه استاندارد برای نام‌گذاری URLها، همیشه باید به داکیومنت مراجعه کنین تا بفهمید که API چجوری کار می‌کنه. یک API ممکنه URLای مانند view_widgets/ داشته باشه در حالی که API دیگری ممکنه از widgets/all/ استفاده کنه.میبینید؟؟؟ هیچ قاعده و قانونی وجود نداره!!!!!!!!!!!!اما نگران نباشید، اینجاس که REST پا به میدون میذاره تا ما رو از این آشفتگی نجات بده.حالا REST چیه؟؟؟خب REST مخفف Representational State Transfer (نماینده انتقال وضعیت) است. این اصطلاحیه که توسط "روی فیلدینگ" برای توصیف راه استاندارد ایجاد APIهای HTTP ابداع شده. اون متوجه شد که چهار عمل رایج (مشاهده، ایجاد، ویرایش و حذف) مستقیماً به متدهای HTTP که قبلاً پیاده‌سازی شده‌اند نگاشت می‌شوند: GET، POST، PUT، DELETE.اگر با HTTP آشنا نیستین، ممکنه با بعضی از این متدها آشنا نباشید. بنابراین اجازه بدید خلاصه ای از متدهای HTTP ارائه بدم.متدهای HTTP:از نظر فنی 8 متد مختلف HTTP وجود داره:GET POST PUT DELETE OPTIONS HEAD TRACE CONNECTبیشتر اوقات، وقتی در مرورگر خودمون در حال کلیک کردن هستیم، فقط از متد "HTTP، "GET استفاده می کنیم. GET زمانی استفاده می شه که شما در حال «دریافت» منبعی از اینترنت هستید. وقتی که فرمی رو ارسال می کنین، معمولاً از متد POST برای "پست کردن داده ها" به وب سایت استفاده می کنید. در مورد متد های دیگه هم بگم که، بعضی از مرورگرها حتی همه اونهارو پشتیبانی نمیکنن. با این حال، چیزی که مهمه اینه که ما یکسری افعال داریم که این متدها برای توصیف اون عمل یا فعل به ما کمک میکنن. ما از کتابخانه های سرویس گیرنده استفاده خواهیم کرد که از قبل می دونن چجوری از متدهای مختلف HTTP استفاده کنن.مثالی از REST:بیایین به چند نمونه از آنچه که یک API را "RESTful" می کنه نگاه کنیم. ما از همون مثال ویجتمون استفاده میکنیم.اگر بخواهیم همه ویجت ها را مشاهده کنیم، URL به شکل زیر خواهد بود:GET http://example.com/widgetsبرای ایجاد یک ویجت به شکل زیر عمل میکنیم:POST http://example.com/widgets Data: name = Foobarبرای مشاهده ویجت به تنهایی از id اون استفاده میکنیم:GET http://example.com/widgets/123و برای آپدیت یک ویجت به شکل زیر عمل میکنیم : PUT http://example.com/widgets/123 Data: name = New name color = blueو در آخر برای حذف به شکل زیر عمل میکنیم : DELETE http://example.com/widgets/123خب حالا دیدید چقدر منظم و سازمان یافته تر شد؟ به این میگن RESTful API ??آناتومی REST URL ها:ممکنه از مثال های قبلی متوجه شده باشید که URL های REST از یک سینتکس یا طرح نامگذاری ثابت استفاده می کننن. وقتی که با یک API تعامل دارید، تقریبا همیشه در حال دستکاری یک نوع کلی از داده ها(یک نوع شی) هستید. در مثال قبلی ما، این شی همان widget است که در اصطلاح REST بهش Resource گفته میشه. قسمت اول URL همیشه به صورت جمع منبع است:/widgetsاین همیشه هنگام مراجعه به مجموعه از منابع استفاده می‌شه (نمایش لیستی از آن شی و تغییر یکی از آن اشیا). وقتی میخواین با یک resource خاص کار کنید، id اون رو به URL اضافه می کنید./widgets/123این URL زمانی استفاده می شه که می خواهید منبع خاصی رو "مشاهده"، "ویرایش" یا "حذف" کنین.منابع یا Resource های تو در تو:بیاین فرض کنیم هر ویجت ما یک شی داده دیگه داره به اسم users(لیستی از کاربران که به آن ویجت خاص در ارتباط هستند) به نظرتون ساختار URLش چه شکلی میشه؟؟؟برای لیست کردن همه users ها:GET /widgets/123/usersبرای ایجاد یک user جدید : POST /widgets/123/users Data: name = Andrewمنابع تو در تو در URL ها کاملا قابل قبول هستن. با این حال، این بهترین روش نیست که بیش از دو سطح به URL خود عمق بدید.چون شما می تونید به سادگی به اون منابع تودرتو با id مراجعه کنید نه اینکه اونهارو در والدین خودشون قرار بدید. مثلا:/widgets/123/users/456/sports/789میتونیم ساده ترش کنیم : /users/456/sports/789و حتی ساده تر :/sports/789کدهای وضعیت HTTP:بخش مهم دیگه REST پاسخ دادن با کد وضعیت مناسب و صحیح برای نوع درخواستی است که انجام شده است. اگر با کدهای وضعیت HTTP آشنا نیستید، یک خلاصه سریع ازشون آوردم. وقتی درخواست HTTP می‌کنید، سرور پاسخ را همراه با یک کد میفرسته که مربوط به موفقیت یا عدم موفقیت درخواست و اطلاعاتی در مورد پاسخ هستش. چهار سطح مختلف از کدهای وضعیت وجود داره:2xx = Success3xx = Redirect4xx = User error5xx = Server errorلیستی از مهمترین کدهای وضعیت:Success codes:200 - OK (the default)201 - Created202 - Accepted (often used for delete requests)User error codes:400 - Bad Request (generic user error/bad data)401 - Unauthorized (this area requires you to log in)404 - Not Found (bad URL)405 - Method Not Allowed (wrong HTTP method)409 - Conflict (i.e. trying to create the same resource with a PUT request)فرمتهای پاسخ دهی یک API:وقتی درخواست HTTP می کنین، می تونین فرمتی رو که می خواهید دریافت کنید رو هم مشخص کنین. به عنوان مثال، با درخواست یک صفحه وب، می خواهید فرمت اون HTML باشه، یا اگه در حال دانلود یک تصویر هستید، فرمت بازگشتی باید یک تصویر باشه. با این حال، این مسئولیت سروره که در قالب درخواست شده پاسخ بده.جیسون به سرعت به فرمت انتخابی برای REST API تبدیل شده. جیسون یک سینتکس سبک وزن و خوانا داره که به راحتی قابل دستکاریه. بنابراین هنگامی که یک کاربر از API ما درخواستی میکنه و JSON را به عنوان قالبی که ترجیح می دهد مشخص می کنه:GET /widgets Accept: application/jsonخب API ما آرایه ای از ویجت ها را با فرمت JSON برمی گردونه:[ { id: 123, name: 'Simple Widget' }, { id: 456, name: 'My other widget' } ]اگر کاربر فرمتی رو درخواست کنه که ما اون رو پیاده سازی نکرده ایم، چه کار می کنیم؟ شما می تونید نوعی خطا ایجاد کنید، اما من توصیه می کنم JSON رو به عنوان فرمت پاسخ استاندارد خود اعمال کنید. اون فرمتی است که توسعه دهندگان شما می خوان ازش استفاده کنن. دلیلی برای پشتیبانی از فرمت های دیگه وجود نداره مگر اینکه قبلاً یک API داشته باشید که نیاز به پشتیبانی مجدد داشته باشه.ساخت یک RESTful API ساده:در واقع ساختن یک REST API عمدتاً خارج از محدوده این آموزشه چون پیاده سازیش در هر زبان برنامه نویسی متفاوته، اما من یک مثال کوتاه با استفاده از Ruby با استفاده از کتابخونه ای به نام Sinatra ارائه می کنم:require 'sinatra' require 'JSON' require 'widget' # our imaginary widget model # list all get '/widgets' do Widget.all.to_json end # view one get '/widgets/:id' do widget = Widget.find(params[:id]) return status 404 if widget.nil? widget.to_json end # create post '/widgets' do widget = Widget.new(params['widget']) widget.save status 201 end # update put '/widgets/:id' do widget = Widget.find(params[:id]) return status 404 if widget.nil? widget.update(params[:widget]) widget.save status 202 end delete '/widgets/:id' do widget = Widget.find(params[:id]) return status 404 if widget.nil? widget.delete status 202 end احراز هویت APIها:در برنامه‌های کاربردی وب معمولی، احراز هویت معمولاً با پذیرش نام کاربری و رمز عبور و ذخیره id کاربر در session انجام می‌شه. مرورگر کاربر یک کوکی با شناسه session ذخیره می کنه. وقتی کاربر از صفحه‌ای در سایت بازدید می‌کنه که نیاز به احراز هویت داره، مرورگر کوکی رو به سرور ارسال می‌کنه، برنامه سمت سرور session رو با اون id جستجو می‌کنه (اگر منقضی نشده باشه)، و از اونجایی که شناسه کاربر در session ذخیره شده، کاربر اجازه مشاهده صفحه رو داره.با یک API، استفاده از session ها برای احراز هویت کاربران لزوما بهترین روش نیست. گاهی اوقات، کاربران شما ممکنه بخوان مستقیماً به API دسترسی داشته باشن، گاهی اوقات کاربر ممکنه به برنامه دیگه ای اجازه دسترسی به API رو از طرف خودش بده.راه حل این امر استفاده از احراز هویت مبتنی بر توکن است. کاربر با نام کاربری و رمز عبور خود وارد سیستم می شه و برنامه با یک توکن منحصر به فرد پاسخ می ده که کاربر می تونه برای درخواست های بعدیش از اون استفاده کنه. یک روش استاندارد برای انجام این کار وجود داره که بسیار محبوب شده که OAuth نامیده می شه. منابع آنلاین زیادی برای پیاده سازی OAuth وجود داره، بنابراین می تونم بگم که خارج از محدوده این آموزشه. اگر از Ruby استفاده می کنین، چندین کتابخانه عالی وجود داره که بیشتر کارها رو خودش برای شما انجام می ده، مانند OmniAuth.امیدوارم، من به اندازه کافی جاهای خالی رو برای شما پر کرده باشم تا بتونید شروع کنید و به درک عمیقی از REST API رسیده باشید.هر گونه سوال یا انتقادی رو در کامنت بنویسید مخلص شما میلاد شیریان?✌