بسیاری از غول های اینترنتی مانند Facebook ، Google ، Github ، Netflix ، Amazon و Twitter دارای REST(ful) API های مخصوص به خودشان هستند که می توانید به آنها برای دریافت یا حتی نوشتن data دسترسی داشته باشید.
اما چرا همه به REST نیاز دارند؟
چرا آن انقدر خوب است و بین همه رایج است؟
مطمئناً این تنها راه انتقال پیام نیست؟
تفاوت بین REST و HTTP چیست؟
خب ، به نظر می رسد REST بسیار انعطاف پذیر و سازگار با HTTP که پروتکل اصلی اینترنت است میباشد. از آنجایی که آن یک سبک معماری است و استاندارد نیست، آزادی عمل زیادی برای بکارگیری بهترین شیوه های پیاده سازی REST را میتوانید در اختیار داشته باشید. آیا گفته بودم که REST یک مکانیزم مستقل از زبان است؟
اگر میخواهید که شیوهای استفاده از RESTful API در #C را یاد بگیرید به شما توصیه میکنم مقاله مورد نظر را مطالعه نمایید.
هدف ما در این مقاله این است که تا حد ممکن REST را شفاف سازی کنیم تا به طور واضح متوجه شوید که چه زمان و چطور از REST استفاده نمایید و اینکه REST در اصل چه چیز میباشد؟
ما برخی از اصول و تعاریف را مرور خواهیم کرد و همچنین تعدادی از بهترین شیوه های پیاده سازی REST را نمایش خواهیم داد. در آخر شما تمام دانشی را که برای پیاده سازی REST API در هر زبان برنامه نویسی که قصد دارید کدنویسی کنید بدست خواهید آورد.
بنابراین در این مقاله ما در مورد موارد زیر صحبت خواهیم کرد:
در مورد REST:
- REST چیست؟
- REST به HTTP محدود میشود؟
- REST و پشتیبانی از HATEOAS
- RESTful API چه معنی میدهد؟
- آیا میتوانیم بیش از حد REST داشته باشیم؟
بهترین شیوه های پیاده سازی REST:
- Abstract API در مقابل Concrete API
- قالب بندی URI. نمونه هایی از URL های خوب در مقابل URL های بد
- Handle کردن خطا
- Status Code ها
- امنیت
- ورژن بندی REST API
- اهمیت مستندسازی
REST چیست؟
REST (Representational State Transfer) یک سبک معماری است که Roy Fielding در پایان نامه دکترای خود “سبکهای معماری و طراحی معماریهای نرم افزار مبتنی بر شبکه” در UC Irvine بنیان گذاری کرده است. او آن را به موازات HTTP 1.1 توسعه داد.
ما در وهله اول از REST به عنوان راهی برای برقراری ارتباط بین سیستم های رایانه ای در شبکه جهانی وب استفاده می کنیم.
آیا REST به HTTP محدود میشود؟
طبق تعریف ، اینطور نیست. اگرچه می توانید پروتکل های کاربردی دیگری را همراه با REST استفاده کنید ، اما HTTP در بحث اجرای REST، قهرمان بی چون و چرا بین تمام پروتکل های کاربردی دیگر است.
REST و پشتیبانی HATEOAS
HATEOAS یا REST به عنوان موتور وضعیت اپلیکیشن، مهمترین ویژگی از هر API مقیاس پذیر و انعطاف پذیر است.
معیار HATEOAS پیشنهاد میکند که کلاینت و سرور به طور کامل با استفاده از hypermedia با یکدیگر ارتباط برقرار کنند.
چند مزیت استفاده از hypermedia:
- طراحان API را قادر می سازد به جای اینکه هر آنچه را که می توانند در هر response قرار دهند ، یک چیز را به طور شایسته ارائه دهند و لینکهای hypermedia به endpoint های مربوطه را ارائه داده و بنابراین طراحی را جدا کنند.
- به تکامل و بالغ شدن یک API کمک می کند.
- این امکان را در اختیار کاربر قرار میدهد تا API را عمیقتر کاوش کند.
بنابراین روشن است که HATEOAS با هدف ماندگاری در ذهن طراحی شده است.
اینجا میتوانید ببینید که GitHub چطور این کار را انجام میدهد:
1 |
GET https://api.github.com/users/irexpertmarket |
Response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
{ "login": "irExpertMarket", "id": 72489636, "node_id": "MDQ6VXNlcjcyNDg5NjM2", "avatar_url": "https://avatars3.githubusercontent.com/u/72489636?v=4", "gravatar_id": "", "url": "https://api.github.com/users/irExpertMarket", "html_url": "https://github.com/irExpertMarket", "followers_url": "https://api.github.com/users/irExpertMarket/followers", "following_url": "https://api.github.com/users/irExpertMarket/following{/other_user}", "gists_url": "https://api.github.com/users/irExpertMarket/gists{/gist_id}", "starred_url": "https://api.github.com/users/irExpertMarket/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/irExpertMarket/subscriptions", "organizations_url": "https://api.github.com/users/irExpertMarket/orgs", "repos_url": "https://api.github.com/users/irExpertMarket/repos", "events_url": "https://api.github.com/users/irExpertMarket/events{/privacy}", "received_events_url": "https://api.github.com/users/irExpertMarket/received_events", "type": "User", "site_admin": false, "name": "expertmarket", "company": null, "blog": "https://www.expertmarket.ir", "location": null, "email": null, "hireable": null, "bio": null, "twitter_username": null, "public_repos": 0, "public_gists": 0, "followers": 0, "following": 0, "created_at": "2020-10-07T06:59:36Z", "updated_at": "2020-10-07T07:06:58Z" } |
همانطور که میبینید، علاوه بر اطلاعات مهم مورد درخواست توسط کلاینت، میتوانید دسته ای از لینکهای hypermedia مرتبط را در response مشاهده کنید که قسمتهای دیگر API را در اختیار شما قرار میدهد که در صورت تمایل میتوانید در آنها کاوش نمایید.
RESTful API چه معنی میدهد؟
“RESTful” به چند ویژگی اشاره میکند:
- معماری Client-server: سرویس کاملی است که شامل “کلاینت” که قسمت front و “سرور” که قسمت backend کل سیستم است.
- Stateless: سرور نباید هیچ وضعیتی را بین request ها ذخیره نماید. وضعیت session کاملا منحصر به کلاینت مورد نظر است. طبق تعریف REST: همه تعاملات stateless ،REST هستند. به عبارت دیگر ، هر request مستقل از هرگونه request قبلی که در آن وجود دارد ، شامل تمام اطلاعات لازم برای یک connector جهت درک آن request مورد نظر است.
- Cacheable: کلاینت باید قادر باشد تا response ها را در یک cache برای performance بهتر ذخیره نماید.
بنابراین RESTful API یک سرویسی است که از این قوانین تبعیت میکند (خوشبختانه) و از متدهای HTTP برای دستکاری کردن مجموعه resource ها استفاده میکند.
اما چرا ما باید از RESTful API ها استفاده نماییم؟
زیرا آنها شیوه ای آسان ، انعطاف پذیر و مقیاس پذیر برای ساخت برنامه های توزیع شده از طریق اینترنت در اختیار ما قرار میدهند.
آیا ما میتوانیم خیلی زیاد REST داشته باشیم؟
بله درست حدس زدید، ما میتوانیم.
اما هرچیزی زیادش میتواند بد باشد.
برای ایجاد خدمات و اپلیکیشنهای خوب، ما کمی باید واقع گرایانه به مسئله نگاه کنیم. درک و شناخت یک تئوری مهم است، اما پیاده سازی آن تئوری چیزی بین کاربرد بد، خوب و عالی است. پس باهوش باشید و در حین پیاده سازی، کاربر نهایی را در ذهنتان در نظر داشته باشید.
بنابراین اجازه دهید سراغ برخی از نکات مهم که باعث درخشش API می شود و کار کاربران را بسیار آسان تر میسازد برویم.
API های Abstract در مقابل API های Concrete
هنگام توسعه نرم افزار، ما اغلب از abstract و polymorphism برای پیاده سازی اکثر سناریوها استفاده میکنیم. ما می خواهیم تا حد امکان از کدهایمان در جاهای مختلف استفاده نماییم.
بنابراین آیا باید API های خود را نیز به همین روش بنویسیم؟
خب ، این دقیقاً در مورد API صدق نمی کند. برای REST API ها، concrete بهتر از abstract است. میتونید حدس بزنید چرا؟
اجازه دهید مثالی را به شما نشان دهم:
فرض کنید دو ورژن متفاوت از API وجود دارد. ورژن اول دارای یک entities/ است و ورژن دوم شامل owners، /blogs/ و blogposts
/ به صورت جداگانه است.
کدامیک از این ورژنها برای شما به عنوان یک توسعه دهنده، توصیفی تر به نظر می رسد؟ کدامیک را ترجیح میدهید استفاده کنید؟
من خودم همیشه ورژن دوم را انتخاب میکنم.
قالب بندی URI. مثالهایی از URL خوب در مقابل URL بد
اینجا مورد دیگری از بهترین شیوه های پیاده سازی REST API وجود دارد. بهتر است که چطور endpoint هایتان را قالب بندی نمایید؟
اگر از رویکرد توسعه نرم افزار استفاده کنید ، در نهایت با چنین چیزی مواجه خواهید شد:
/getAllBlogPosts
/updateBlogPost/12
/deleteBlogPost/12
/getAuthorById/3
/deleteAuthor/3
/updateAuthor/3
این نکته را در نظر داشته باشید… تعداد زیادی endpoint وجود دارد که هریک کار متفاوتی را انجام میدهد. سیستم بهتری برای نظم دادن این به هم ریختگی وجود دارد.
resource را مانند یک اسم و متد HTTP را مانند یک فعل در نظر بگیرید که در اینصورت، شما با چیزی به صورت زیر مواجه میشوید:
GET /blogposts
– تمام پست بلاگ ها را برمیگرداند.GET /blogposts/12
– پست بلاگ با آیدی 12 را برمیگرداند. POST /blogposts
– یک پست بلاگ جدید را اضافه میکند و جزییات را برمیگرداند.DELETE /blogposts/12
– بلاگ پست با آیدی 12 را حذف میکند.GET /authors/3/blogposts
– تمام بلاگ پستهای انتشار شده توسط نویسنده با آیدی 3 را برمیگرداند.
این یک روش تمیزتر و دقیق تر برای ایجاد API است و خیلی سریع برای کاربر نهایی شفاف و واضح به نظر خواهد رسید.
شما حتی میتوانید از نام مفرد به جای اسم جمع در نام گذاری resource ها استفاده کنید. این کاملا به شما بستگی دارد.
مدیریت کردن خطا
جنبه دیگری از ایجاد API مربوط به مدیریت کردن خطاهاست. چند راه خوب برای مدیریت کردن خطا وجود دارد.
ببینیم غول های اینترنتی چطور این کار را انجام میدهند:
Twitter:
- Request:
GET https://api.twitter.com/1.1/account/settings.json
- Response: Status Code 400
1 |
{"errors":[{"code":215,"message":"Bad Authentication data."}]} |
Twitter کد Status را به همراه کد خطا و یک توضیح کوتاه در مورد خطایی که رخ داده است به ما میدهد. آنها این امکان را در اختیار شما گذاشتند تا صفحه مربوط به کدهای Response شان را ببینید.
Facebook:
- request:
GET https://graph.facebook.com/me/photos
- Response: Status Code 400
1 2 3 4 5 6 7 8 |
{ "error": { "message": "An active access token must be used to query information about the current user.", "type": "OAuthException", "code": 2500, "fbtrace_id": "DzkTMkgIA7V" } } |
فیسبوک، توضیح بیشتری را در مورد خطای رخ داده در اختیار شما قرار میدهد.
Twilio:
- request:
GET https://
api.twilio.com/2010-04-01/Accounts/1234/IncomingPhoneNumbers/1234
- Response: Status Code 404
1 2 3 4 5 6 7 8 9 |
<?xml version='1.0' encoding='UTF-8'?> <TwilioResponse> <RestException> <Code>20404</Code> <Message>The requested resource /2010-04-01/Accounts/1234/IncomingPhoneNumbers/1234 was not found</Message> <MoreInfo>https://www.twilio.com/docs/errors/20404</MoreInfo> <Status>404</Status> </RestException> </TwilioResponse> |
Twilio به صورت پیشفرض، response را به صورت XML به شما میدهد و برای دریافت جزییات بیشتر در مورد خطای رخ داده، لینک مستند مربوط به خطای مورد نظر را نیز در اختیار شما قرار میدهد.
همانطور که می بینید ، رویکردهای مدیریت خطا از اجرا تا اجرا متفاوت است.
نکته مهم این است که کاربر را به حال خود رها نکنید تا نداند که چه اتفاقی افتاده است و بی هدف به صورت سردرگمانه بخواهد در دریای وسیعی از StackOverflow، مشکل پیش آمده مورد نظر را جست و جو نماید.
Status Code ها
هنگام طراحی REST API، ما توسط HTTP Status Code ها، با کاربر API ارتباط برقرار میکنیم. تعداد زیادی status code وجود دارد که تعدادی response های احتمالی را توصیف میکند.
اما از چه تعداد status code بهتر است استفاده کنیم؟ آیا باید برای هر وضعیتی، از یک status code منحصر به فرد استفاده کنیم؟
همانند بسیاری از موارد در زندگی ، اصول KISS نیز در اینجا اعمال می شود. بیش از 70 مورد status code وجود دارد. آیا آنها را کاملا میشناسید؟ آیا کاربر بالقوه API آنها را میشناسد یا اینکه باید آن را در گوگل جست و جو کند؟
اکثر توسعه دهندگان با اکثر status code های رایج آشنا هستند:
200 OK
400 Bad Request
500 Internal Server Error
با همین سه مورد میتوانید اکثر عملکردهای REST API تان را پوشش دهید.
دیگر کدهای رایج عبارتند از:
201 Created
204 No Content
401 Unauthorized
403 Forbidden
404 Not Found
ما می توانیم از این موارد برای کمک به کاربر در درک سریع نتیجه استفاده کنیم. اگر فکر می کنید status code به اندازه کافی توصیفی نیست، احتمالاً باید مانند آنچه در قسمت مدیریت خطا بحث کردیم ، نوعی پیام را در آن بگنجانیم. یک بار دیگر ، ما باید واقع بین باشیم و با استفاده از تعداد محدودی از کدها و پیامهای توصیفی به کاربر کمک کنیم.
امنیت
چیز زیادی برای گفتن در مورد امنیت REST API وجود ندارد. زیرا REST با امنیت سروکار ندارد. آن به مکانیسمهای استاندارد HTTP مانند basic authentication یا digest authentication متکی است.
هر request باید روی HTTPS ایجاد شده باشد.
ترفندهای زیادی برای بهبود امنیت REST API شما وجود دارد ، اما به دلیل ماهیت stateless در REST، هنگام پیاده سازی آنها باید محتاط باشید. به خاطر بسپارید که state آخرین request از پنجره خارج می شود و client در جاییست که باید state ذخیره و تأیید شود.
request های Timestamping و logging میتوانند تا حدودی کمک کننده باشند.
ورژن بندی REST API
شما قبلا REST API خودتون رو نوشتید و نتیجه خیلی موفقیت آمیز بوده و بسیاری از مردم از آن استفاده کرده و راضی بوده اند. اما امکان دارد که شما مقداری قابلیت های جدید داشته باشید که باعث نقض شدن دیگر قسمتهای سیستم میشود.
اما نترسید، راه حلی برای آن وجود دارد.
قبل از اینکه ما API مان را بسازیم، میتوانیم با مشخص کردن ورژن API به عنوان پیشوند در endpoint ها آنها را ورژن بندی نماییم:
1 |
https://api.example.com/v1/authors/2/blogposts/13 |
با این شیوه ما میتوانیم هرزمان که تغییراتی در API مان دادیم، شماره ورژن API را بالا ببریم (به عنوان مثال: v3،v2…). این امر همچنین به کاربران نشان می دهد که تغییری جدی در سیستم اتفاق افتاده است و آنها باید هنگام استفاده از نسخه جدید مراقب باشند.
اهمیت مستندسازی
این یکی چیز واضحی است. شما میتوانید بهترین طراح API در جهان باشید اما بدون مستندسازی، API شما کاملا بی روح است.
مستندات مناسب برای هر محصول نرم افزاری و خدمات وب ضروری است.
ما مطمئنا میتوانیم با استفاده از سینتکس واضح و توصیفی و با ثبات بودن، به کاربران کمک کنیم. اما هیچ جایگزین واقعی برای صفحات مستندات خوب وجود ندارد.
تعدادی مثال واقعی:
https://www.twilio.com/docs/api/rest/
https://developers.facebook.com/docs/
https://developers.google.com/maps/documentation/
و خیلی مثالهای دیگر.
ابزارهای زیادی وجود دارد که میتواند در مستندسازی API به شما کمک کند. اما فراموش نکنید که اون حس انسانی رو هم در مستندات خود لحاظ کنید، فقط یک انسان قادر است که به درستی دیگری را درک کند.
نتیجه گیری
ما مفاهیم زیادی را در مورد ساخت REST API بررسی کردیم و تعدادی از بهترین شیوه های پیاده سازی REST API را پوشش دادیم. اینها زمانی که به یکباره به کار برده میشوند امکان دارد کمی عجیب و طاقت فرسا به نظر بیایند، اما سعی کنید API خودتان را بسازید و چندتا از بهترین شیوه های پیاده سازی REST API را که در این مقاله یاد گرفتید را بکار ببرید.
یک API تا حد امکان کوچک را بسازید و ببنید که چطور به نظر میرسد. فقط با پیروی از این چند شیوه، تعجب خواهید کرد که چقدر می تواند خوب پیاده سازی شود.
اگر شما یک توسعه دهنده #C هستید، مقاله ما را در چند راه عالی برای استفاده از RESTful Api در #C بررسی نمایید.