از آنجایی که وب سرویس REST به عنوان پیش فرض برای اکثر سایتها و نرم افزارهای موبایل قرار گرفته، یادگیری پایههای آن امری ضروری به شمار میرود.
بیش از یک دهه از پس از معرفی این محصول یعنی همان وب سرویس REST به عنوان یکی از مهمترین تکنولوژیهای برنامههای تحت وب به شمار میرود. اهیمت آن در حال گسترس همانند سرعت سایر تکنولوژیهای مبتنی بر API است. امروزه هر زبان توسعهای مطرح از بسترهایی جهت ساخت وب سرویس های داراری REST برخوردار است. از این رو شناخت REST و سرویسهای داراری REST برای توسعه دهنده ها و طراحان وب مهم است. این مقاله معماری REST را شرح می دهد سپس به جزئیات مشترک برای تسکهای API محور میپردازد.
درحالی که REST برای Representational State Transfer، که یک سبک و معماری برای برنامه های برنامه های پرتابل شبکه (hypermedia) تحت شبکه است، به کار می رود؛ در درجه نخست REST برای ساخت وب سرویسهای سبک ، نگهداشت پذیر و مقیاس پذیر استفاده میشود.REST از هیچ پروتکلی پیروی نمی کند. در این مقاله من سرویس های داراری REST را بر بستر HTTP تشریح می کنم.
ویژگی های وب سرویس های مبتنی بر REST
هر سیستمی از منابعی استفاده می کند.این منابع می تواند تصویر، فایلهای ویدیویی صفحات وب، اطلاعات کسب و کار یا هر آنچه که در سیستم های تحت کامپیوتر قابل اجراست، باشد. هدف سرویس فراهم سازی یک پنجره برای کلاینتهایش است که از این پنجره برای دسترسی به منابع استفاه کنند. طراحان و توسعه دهندگان سرویس می خواهند این سرویس برای پیاده سازی ساده باشند، در دسترس باشند و گسترش آن آسان باشد.یک طراحی داراری REST این شرایط و فراتر از آن را فراهم می سازد.به طور کلی سرویس های دارای REST باید خصوصیات و ویژگی های زیر را دارا باشند که بعدا به تفضیل تویح داده خواهند شد:
ارائه (Presentation)
پیغام
URI
رابط واحد
وابسته نبودن به مکان(حالت) خاصی (Stateless)
ایجاد اتصال میان منابع
ذخیره سازی
ارائه
تمرکز یک سرویس دارای REST بر روی منابع و اینکه چگونه قابلیت دسترسی را به این منابع فراهم سازند است. یک منبع می تواند به راحتی به عنوان یک OOP به کار رود.یک منبع می تواند سایر منابع را شامل شود.برای طراحی یک سیستم اولین کار شناخت منابع و تعیین اینکه این منابع چگونه به هم مرتبط اند است. این کار شبیه به اولین گام برای طراحی پایگاه داده است: شناخت موجودیت ها و روابط.
هنگامی که ما منابع خود را شناختیم قدم بعدی یافتن راهی برای معرفی این منابع به سیستم است.از آنجایی که REST هیچ محدودیتی برای قالب ارائه منابع قائل نیست، شما میتوانید از هر قالبی برای معرفی منابع استفاده کنید.
برای مثال وابسته به نیازهایتان، شما می توانید تصمیم بگیرید که از JSON یا XML استفاده کنید. اگر شما در حال ساخت سرویس وب هستید میتوانید از AJAX برای صفحات وب استفاده کنید بعد از AJAX، JSON انتخاب خوبی خواهد بود.XML می تواند منابع پیچیده تری را به سیستم معرفی کند. برای مثال منبعی تحت عنوان Person می تواند به صورت زیر ارائه شود:
لیست شماره ۱: ارائهای از یک سیستم توسط واسط JSON
{ "ID": "1", "Name": "Amirhosein araghi", "Email": "info@sabio.ir", "Country": "Iran" }
لیست شماره ۲: ارائهای از یک سیستم توسط واسط XML
<Person> <ID>1</ID> <Name>Amirhosein araghi</Name> <Email>info@sabio.ir</Email> <Country>Iran</Country> </Person>
در حقیقت شما میتوانید از بیش از یک قالب استفاده کنید و تصمیم بگیرید از قالب وابسته به نوع کلاینت یا برخی معیارهای درخواست بهره ببرید.از هر قالبی که استفاده می کنید یک ارائه خوب باید از برخی کیفبتهای مشخص برخوردار باشد:
- هم کلاینت و هم سرور بهتر است که قادر به درک این قالب باشند
- یک ارائه بهتر است که قادر به معرفی کامل از یک منبع باشد.اگر نیاز به معرفی بخشی از منبع باشد، شما باید به فکر تجزیه این منبع به چندین منبع کوچک باشید.تقسیم منابع بزرگ به منابع کوچک به شما اجازه جابهجایی سریعتر را میدهد.منابع کوچکتر نیاز به زمان کمتری برای تولید و جابهجایی دارند که به منزله داشتن سرویسی سریعتر است.
- ارائه بهتر است که توانایی اتصال منابع به یکدیگر را داشته باشد.این امر میتواند با قرار دادن URI یا یک ID منحصربفرد به منابع مربوط در ارائه، انجام گیرد(که در بخشهای بعد به تفضیل بیان خواهد شد)
پیغام
کلاینت و سرویس از طریق پیام با یکدیگر به صحبت می پردازند.کلاینت درخواستی را به سرور می فرستد و سرور به آن پاسخ میدهد.جدا از داده واقعی، این پیغامها همچنین شامل ابرداده(metadata) درمورد پیغام میشوند. این امری مهم است که برای طراحی وب سرویسهای دارای REST، پیش زمینه ای راجع به HTTP 1.1، قالبهای درخواست و پاسخ داشته باشید.
درخواست HTTP
یک درخواست HTTP دارای فرمتی است که در شکل ۱ نمایش داده شده است.

شکل ۱ : قالب درخواست HTTP
<VERB> یکی از متدها به صورت GET، PUT، POST، DELETE، OPTIONS و یا نظیر اینهاست.
<URI <URI منبع بسته به اینکه کدام عملیات درحال اجراست، میباشد.
<HTTP VERSION> نسخه HTTP را مشخص می کند که غالبا “HTTP 1.1” است.
<Request Header> شامل ابردادهای به عنوان مجموعه ای از جفتهای کلیدواژه از سرسازها(Header) و ارزششان است. این تنظیمات شامل اطلاعاتی درباره پیغام و فرستنده آن همچون نوع کلاینت، قالب پشتیبانی کلاینت، نوع قالب بدنه پیغام، تنظیمات ذخیرهسازی برای پاسخ و اطلاعات دیگری می شود.
<Request Body> پیغام واقعی است. در یک سرویس دارای REST این قسمت همانجایی است که ارائه ای از منبع در پیغام قرار میگیرد.
هیچ برچسبی برای مشخص کردن آغاز و پایان یک مجموعه در پیغام HTML وجود ندارد.
فهرست شماره ۳ نمونهای از درخواست POST را که درون یک منبع جدید از PERSON اعمال میشود،نشان می دهد.
لیست شماره ۳ : نمونه ای از یک درخواست POST
شما می توانید دستور POST را ببینید که همراه با URI و نسخه HTTP آمده است.این درخواست همچنین شامل برخی سرسازهای درخواست است. Host یک آدرس از سرور است. Content-Type درمورد نوع محتویات در بدنه پیغام سخن میگوید. Content-Length طول داده را در بدنه پیغام نشان میدهد. Content-Length برای مشخص کردن تمام بدنه پیغامی که دریافت شده است هم استفاده میشود.توجه کنید که هیج برچسب آغاز یا پایانی در پیغام وجود ندارد.
لیست شماره ۴ یک درخواست GET واقعی را نشان می دهد که توسط مرورگر من زمانی که برای دیدن مشخصات فنی HTTP 1.1 سایت w3.org تلاش کرده ام را نشان میدهد.
لیست شماره ۴: یک درخواست GET
GET http://www.w3.org/Protocols/rfc2616/rfc2616.html HTTP/1.1 Host: www.w3.org Accept: text/html,application/xhtml+xml,application/xml; … User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 … Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,hi;q=0.6
هیچ بدنه پیغامی در این درخواست وجود ندارد. سرساز Accept به سرور راجع به قالبهای مختلف مورد پشتیبانی کلاینت می گوید. یک سرور، اگر از بیش از یک فرمت برای ارائه استفاده کند می تواند تصمیم بگیرد که از چه فرمتی بسته به ارزش سرساز Accept برای پاسخ در زمان اجرا استفاده کند. User-Agent اطلاعاتی درباره نوع کلاینتی که درخواست را داده است به دست می دهد. Accept-Encoding/Language درباره نوع رمزنگاری و زبان مورد پشتیبانی کلاینت صحبت میکند.
پاسخ HTTP
شکل ۲ قالب یک پاسخ HTTP را نشان میدهد.

شکل ۲ : قالب پاسخ HTTP
سرور <response code> را که شامل وضعیت پاسخ می شود برمی گرداند.کد این پاسخ به صورت کد وضعیت ۳ شمارهایHTTP نمایش داده می شود.
<Response Header> ابرداده و تنظیمات مربوط به پاسخ را شامل میگردد.
<Response Body> اگر درخواست موفق باشد شامل ارائه میشود.
لیست شماره ۵ یک پاسخ واقعی از درخواست من در لیست شماره ۳ است:
لیست شماره ۵ : یک پاسخ واقعی از یک درخواست GET
HTTP/1.1 200 OK Date: Sat, 23 Aug 2014 18:31:04 GMT Server: Apache/2 Last-Modified: Wed, 01 Sep 2004 13:24:52 GMT Accept-Ranges: bytes Content-Length: 32859 Cache-Control: max-age=21600, must-revalidate Expires: Sun, 24 Aug 2014 00:31:04 GMT Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns='http://www.w3.org/1999/xhtml'> <head><title>Hypertext Transfer Protocol -- HTTP/1.1</title></head> <body> ...
کد پاسخدهی ۲۰۰ به معنای OK است که میگوید همهچیز به خوبی پیش رفته است و بدنه پیغام پاسخ شامل یک ارائه معتبر از منبعیست که من درخواست کردهام. در این حالت ارائه، یک سند HTML است که توسط سرساز Content-Type در سرساز پاسخ اعلان شده است. سرسازها در پیغام واضح هستند ولی من برخی از آنها را در آینده در این مقاله توضیح خواهم داد.ویژگیهای زیاد دیگری وجود دارد.شما برای بررسی کردن این نوع درخواستها و پاسخهای HTTP می توانید از یک ابزار رایگان تحت عنوان Fiddler استفاده کنید.
آدرس دهی منابع
REST از هر منبع میخواهد که حداقل یک URI داشته باشد. یک سرویس دارای REST از یک سلسله مراتب دایرکتوری همچون URIهای قابل خواندن توسط انسان برای آدرس دهی به منابع اش استفاده می کند. کار یک URI شناسایی یک منبع یا مجموعه ای از منابع است. عملیات اصلی شناسایی توسط یک فعل(verb) HTTP است. URI نباید هیچ چیزی راجع به عملیات بگوید. این امر ما را برای فراخوانی URIهای یکسان با فعلهای متفاوت HTTP برای عملیاتهای مختلف قادر میسازد.
فرض کنید ما یک پایگاه داده از افرادی داریم و میخواهیم آن را در یک دنیای خارجی از طریق یک سرویس نمایش دهیم. یک منبع از PERSON میتواند بدین صورت آدرس دهی شود:
1 | http://MyService/Persons/1 |
این URI فرمت زیر را دارد:
1 | Protocol://ServiceName/ResourceType/ResourceID |
در اینجا توصیههایی برای URI خوش ساخت آمده است:
- از نامهای جمع برای نامگذاری منابعتان استفاده کنید
- از استفاده از فاصله گذاری بپرهیزید چون باعث سردرگمی میشود. به جای آن از _(خط زیرین) یا – (خط تیره) استفاده کنید.
- یک URI حساس به کوچکی و بزرگی حروف است. من از نگارش شتری(camel case) برای وضوح بیشتر استفاده کردهام. شما می توانید از URI با حروف تماما کوچک بهره ببرید.
- شما میتوانید مکالمه منحصر به خودتان را داشته باشید ولی در هنگام ساخت سرویس نامتناقض بمانید.مطمئن باشید که کلاینت شما از این مکالمات آگاه است. این امر کار را برای کلاینتهای شما اگر از سلسه مراتب منابع و URIای که شما از آن پیروی می کنید آگاه باشند، جهت ساخت URIهای برنامه نویسی آسان می کند.
- یک URI خوب هیچگاه تغییر نمیکند؛ بنابراین پیش از تصمیم گیری راجع به URI سرویستان فکر کنید.اگر نیاز به تغییر مکان منبع خود دارید، URI سابق را از بین نبرید. از کد ۳۰۰ استفاده کنید و کلاینت را به آدرس جدید راهنمایی کنید.
- از افعال برای نام منابعتان تا زمانی که واقعا یک عملیات یا پردازش درحال اجراست بپرهیزید. افعال بیشتر مناسب نامهای عملیاتها هستند. برای مثال یک سرویس دارای REST نباید مثل نمونههای زیر باشد:
http://MyService/FetcthPerson/1 یا http://MyService/DeletePerson?id=1.
پارامترهای Query در URI
URI قبلی با کمک یک پارامتر کوئری (پرس و جو،Query) ساخته شد:
http://MyService/Persons?id=1
رویکرد پارامتر کوئری به خوبی کار می کند و REST محدودیتی برای استفاده از این رویکرد ندارد، هرچند این رویکرد مضراتی هم دارد.
• افزایش پیچیدگی و کاهش خوانایی، که این دو مشکل درصورتی که تعداد پارامترها افزایش یابد بدتر هم خواهد شد
• موتورهای جستجو خرنده (Search-engine crawlers) و شاخص نظیر Google URIها را با پرامترهای کوئری نمیپذیرند.اگر درحال توسعه وب هستید این ضرر بزرگی خواهد بود که بخشی از وب سرویس شما از موتورهای جست و جو پنهان باشد.
هدف اصلی از پارامترهای کوئری فراهم سازی پارامترهایی برای یک عملیات که نیاز به اقلام داده(Data Item) دارد،است. برای مثال اگر شما میخواهید قالب ارائه توسط کلاینت انتخاب شود.شما می توانید با پارامتری نظیر مثال پایین به هدف خود برسید:
رابط واحد
سیستمهای دارای REST باید دارای یک رابط واحد باشند. HTTP 1.1 مجموعه ای از متدها را با نام فعل(verb) برای دستیابی به این هدف فراهم می کند. مهمترین این افعال عبارتند از:
یک عملیات امن عملیاتی ست که هیچ تائیری بر روی ارزش اصلی منبع ندارد. برای مثال عملیات ریاضی “تقسیم بر ۱″ یک عملیات امن است زیرا فرقی نمی کند جندبار یک عدد را بر یک تقسیم کنید مقدار آن هیچ گاه تغییر نمیکند. یک عملیات خودپنداره(Idempotent) عملیاتی ست که تنها یک مقدار واحد را می دهد و فرقی نمی کند چند بار این عملیات را اجرا کنید.برای مثال عملیات ریاضی ” ضرب در صفر” یک عملیات خودپنداره(Idempotent) است زیرا فرقی نمی کند چند بار یک عدد را در صفر ضرب کنید پاسخ همواره یکسان است.به طور مشابه یک روش HTTP امن نیز تغییری بر روی منبع موجود در سرور ایجاد نمی کند. یک روش HTTP خودپنداره(Idempotent) هم همواره یک نتیجه را برمیگرداند مهم نیست چندبار اجرا شود. دسته بندی کردن متدها به صورت امن و خودپنداره(Idempotent) کار را برای پیش بینی نتایج در محیط های غیر فابل اطمینان از وب در جایی که کلاینت ممکن است یک درخواست مشابه را مجددا ارسال کند،آسان می کند.
GET شاید محبوب ترین روش در وب باشد. این روش برای واکشی(fetch) یک منبع استفاده می شود.
HEAD تنها سربارهای پاسخ را با یک بدنه خالی برمی گرداند. این روش می تواند در یک سناریو زمانی که تمام ارائه یک منبع را نمیخواهید ،استفاده شود. برای مثال HEAD میتواند برای چک کردن سریع آنکه منبعی بر روی سرور وجود دارد یا نه به کار رود.
روش OPTIONS برای لیست کردن عملیات های مجاز بر روی منبع استفاده می شود. برای مثال درخواست زیر را درنظر بگیرید:
OPTIONS http://MyService/Persons/1 HTTP/1.1HOST: MyService
سرویس پس از شناسایی و تایید اعتبار درخواست چیزی شبیه به زیر را می فرستد:
۲۰۰ OK Allow: HEAD, GET, PUT
خط دوم لیستی از عملیات هایی که برای این کاینت مجاز هستند را شامل می شود.
شما باید از این متدها صرفا برای اهدافی که برای آنها ساخته شده اند استفاده کنید. برای مثال هیچگاه از GET برای ساخت یا پاک کردن یک منبع بر روی سرور استفاده نکنید. اگر این کار را انجام دهید، باعث سردرگم شدن کلاینتها خواهید شد و شاید کلاینتها عملیات هایی را سهوا و بدون اطلاع انجام دهند. برای روشن شدن موضوع بیایید این درخواست را در نظر بگیریم:
GET http://MyService/DeletePersons/1 HTTP/1.1 HOST: MyService
با HTTP 1.1 یک دستور GET برای واکشی منابع بر روی سرور درنظر گرفته شده است.ولی این کار راحتتر خواهد بود اگر سرویس خود را با پاک کردن یک PERSON انجام دهید.این درخواست شاید به درستی کار کند، ولی این یک طراحی REST نیست. به جای آن از متد DELETE برای پاک کردن یک منبع استفاده کنید:
DELETE http://MyService/Persons/1 HTTP/1.1 HOST: MyService
REST یک رابط واحد را توصیه می کند و HTTP این رابط واحد را فراهم می سازد.هرچند این امر که واحد باقی بماند به سازندگان و توسعه دهندگان سرویس مرتبط است.
در ادامه سایر ویژگی های این سرویس ها را بررسی خواهیم کرد
ادامه مطلب...