در حال ارتباط با سرور...




لطفا نظرات و پيشنهادات خود را بمنظور ارتقاء کيفي هرچه بيشتر سايت با ما در ميان بگذاريد.

ویدیوها مقالات کتاب ها اخبار پرسش و پاسخ
برنامه‌های رومیزی مبتنی بر وب زبان های برنامه سازی پایگاه داده سیستم عامل شبکه 
مقاله بگذارید
توسط : hamedkh دسته بندی : مبتنی بر وب تاریخ : 1393-1-12 12:03:49

اگر بیاد داشته باشید در مقاله پیشین با عنوان اصول طراحی سرویس های REST مطالبی را در مورد چگونگی نوشتن API های RESTfull بگونه ای که هم تمیز باشند و هم توسعه دهندگان بتوانند به بهترین شکل ممکن از آنها استفاده نمایند بیان کردیم. در این مقاله قصد داریم نکات دیگری را در این رابطه به شما عزیزان آموزش دهیم.

 

اعمال محدودیت (limit) بر روی فیلد های خروجی API

همانطور که گفته شد برای آنکه کاربران بتوانند به یک یا چند منبع دسترسی پیدا نمایند باید در خواستی را با متد GET به سرویس شما ارسال نمایند. در پاسخ به درخواست انها دو رویکرد وجود دارد. یکی آنکه همیشه کل فیلد های منبع یا منابع را باز گردانید و یا آنکه آنچه را که مورد نیاز کاربر است در اختیار وی قرار دهید. باید گفت کسانی که از API شما استفاده می کنند در بسیاری از مواقع فقط به بخشی از منبع نیاز دارند. بنابراین بهتر است راهکاری را در اختیار آنها قرار دهید تا بتوانند به API شما فیلد های مورد نیازشان را اعلام کنند. به این ترتیب هم API شما بهینه تر عمل می کند و هم آنکه اطلاعات اضافی و غیر ضروری در اختیار کاربران قرار نمی گیرد. علاوه بر این در پهنای باند شبکه صرفه جویی شده و پاسخ به کاربر با سرعت بیشتری می رسد.

برای این منظور پیشنهاد می شود همانند آنچه در مورد search گفتیم عمل شود. مثلا پارامتری با نام fields در url در نظر بگیرید و به کاربر این امکان را دهید تا فیلد های مورد نیازش را بصورت comma separated به API اعلام نماید. در زیر نمونه ای از این نحوه کار آورده شده است :

 

GET /tickets?fields=id,subject,customer_name,updated_at&state=open&sort=-updated_at

پس از انجام عملیات درج و بروزرسانی منبع را نیز بازگردانید:

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

در مورد POST دقت کنید که بهتر است در پاسخ علاوه بر خود منبع، کد HTTP 201  را بازگردانید. علاوه بر آن هدر مربوط به Location را نیز با آدرس مربوط به منبع جدید مقدار دهی نمایید.

 

 

استفاده از HATEOAS:

استفاده از HATEOAS یکی از موارد بحث بر انگیز در هنگام طراحی API های REST است. برخی از طراحان معتقند که لینک های مربوط به برنامه کلاینت باید توسط خود کلاینت (یا بهتر بگوییم برنامه نویس کلاینت) ایجاد گردد و سرویس تنها نقش پاسخ دهی به درخواست ها را بر عهده دارد. اما برخی دیگر معتقدند که در سرویس های REST طراحی باید بر مبنای HATEOAS صورت پذیرد. بدین معنی که API وظیفه دارد نحوه تعامل کلاینت با سرویس را از طریق فراهم کردن لینک هایی در پاسخ تعیین نماید. به بیانی دیگر سرویس علاوه بر داده وظیفه دارد فرا داده هایی (metadata) را در اختیار کلاینت قرار دهد و از طریق آن لینک هایی که در آینده مورد استفاده کلاینت است را برای کلاینت فراهم کند. بعنوان مثال در هنگام گرفتن لیستی از کاربران از سرویس در صورتی که صفحه بندی (pagination) برای نمایش کاربران داشته باشیم، علاوه بر لیست کاربران در فراداده لینک های صفحه بعدی و صفحه قبلی را در اختیار کلاینت قرار می دهیم.

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

 

 

استفاده از JSON در پاسخ ها

در بسیاری از مطالب آموزشی در مورد طراحی API ها گفته می شود که پاسخ ها را در دو فرمت JSON و XML برای کلاینت ها محیی کنید تا کلاینت از هرکدام که خواست استفاده نماید. اما در اینجا می گوییم شاید وقت آن باشد که دیگر فرمت XML را بعنوان پاسخ رها کنیم و تنها از JSON استفاده کنیم. اگرچه فرمت XML کاربرد های بسیاری دارد و مزایای زیادی هم در بسیاری از برنامه ها دارد اما در اینجا باید گفت این فرمت برای پاسخ یک API بسیار طولانی است، پارس کردن ان نیز دشوار است، به آسانی نمی توان آن را خواند و علاوه بر اینها با مدل های داده ای مرسوم در زبان های برنامه نویسی نیز سازگاری زیادی ندارد. بنابه این دلایل و بسیاری از دلایل دیگر، برنامه های متعدد از جمله YouTube، Twitter و ... در حال کنار گذاشتن XML هستند. یکی از دلیل این ادعا هم میتواند اختلاف گرایش به سمت این دو در Google Trend باشد.

 

با تمام این گفته ها، شرایطی ممکن است پیش بیاید که ما مجبور به فراهم کردن هر دوی آنها برای کلاینت ها باشیم. در چنین شرایطی باید کلاینت به نحوی مشخص کند که فرمت مورد انتظارش برای پاسخ چیست. برای این منظور دو روش مرسوم است. یکی مشخ کردن نوع رسانه (media type) از طریق Accept Header و دیگر از طریق URL. پیشنهاد می شود برای آنکه API شما از طریق مرورگر نیز قابل پیشمایش باشد  از طریق URL این کار را انجام دهید. یکی از روش های مرسوم و خوب برای این منظور هم اضافه کردن Extension های .json و .xml به انتهای URL می باشد. 

 

 

نامگذاری پارامتر ها بر اساس snake_case و یا camelCase

اگر شما از JSON برای پاسخ استفاده می کنید، بدلیل  آنکه قاعده نامگذاری در JavaScript بر اساس camelCase است، درست آن است شما نیز برای نامگذاری پارامتر ها از camelCase استفاده نمایید. اما وقتی قرار است در سمت کلاینت کتابخانه هایی با زبان های مختلف داشته باشید بهتر از مبنای کار شما قواعد نامگذاری در ان زبان ها باشد. بعنوان مثال اگر از جاوا یا C# استفاده می کنید بهتر از نام های شما camelCase و در صورتی که از زبان هایی مانند python و یا ruby بهره می گیرد پیشنهاد  می شود از snake_case استفاده نمایید.

 

در اینجا تنها جهت آگاهی شما عزیزان نظرتان را به مقاله ای در IEEE با عنوان An Eye Tracking Study on camelCase and under_score Identifier Styles که در سال 2010 به چاپ رسیده است جلب می کنیم. بر اساس ادعای نویسندگان این مقاله خوانایی  نام گذاری بر اساس snake_case نسبت به camelCase حدود 20%   بهتر است. بنابراین بنظر می رسد در صورت استفاده از snake_case در API احتمالا استفاده کنندگان API شما مثال های مستندات شما را بهتر متوجه خواهند شد و همچنین قابلیت explorability سرویس شما نیز بهبود خواهد یافت.

 

بسیاری از API های معروف از snake_case استفاده می کنند. اما پیشنهاد می شود در صورت استفاده از این شیوه نامگذاری کتابخانه ای در سمت کلاینت داشته باشید که snake_case را به فرمت مرسوم در زبان برنامه نویسی سمت کلاینت تبدیل نماید. مثلا اگر کلاینت شما با C# نوشته می شود، قبل از استفاده از پاسخ دریافتی از سرویس، نام های پارامتر ها در پاسخ را بصورت camelCase تبدیل کنید.

 

 

فراهم نمودن خروجی زیبا و پشتیبانی از فشرده سازی gzip

همانطور که در بخش های مختلف این مقاله آموزشی بیان کردیم API شما باید از طریق مرورگر قابل دسترس باشد. این بدین معناست که خروجی API در مرورگر قابل مشاهده خواهد بود. بنابراین بهتر است خروجی چاپ شده در مرورگر براحتی قابل خواندن باشد. گاهی اوقات بمنظور صرفه جویی در پهنای باند و ترافیک شبکه از فشرده سازی white-space compression استفاده می شود که این مسئله باعث می شود خروجی API در مرورگر چندان زیبا و خوانا نباشد. البته برخی ها با استفاده از پارامتر هایی مانند ?prety=true این امکان را برای کاربران فراهم می آورند تا امکان مشاهده خروجی زیبا (pretty print) را داشته باشند اما پیشنهاد می شود بطور پیشفرض این قابلیت را در API های خود فعال نمایید چراکه می توانید اختلاف هزینه انتقال داده را با پشتیبانی از فشرده سازی gzip جبران نمایید و در عین حال API شما از نظر در دسترس بودن و خوانا بودن وضعیت بهتری را خواهد داشت. 

 

 

نحوه wrap کردن داد ها در پاسخ

بسیاری از API ها داده های خروجی خود را بصورت زیر wrap می کنند :

 

{
  "data" : {
    "id" : 123,
    "name" : "John"
  }
}

دلایل مختلفی برای اینگونه wrap کردن داده ها وجود دارد. مثلا این کار باعث می شود بتوانیم علاوه بر داده، فراداده هایی  (metadata) را نیز در خروجی اضافه کنیم، اطلاعاتی در مورد صفحه بندی را در اختیار کلاینت ها قرار دهیم و یا اطلاعاتی در مورد HTTP header ها را در اختیار کلاینت هایی قرار دهیم که امکان دسترسی به این هدر ها را ندارند. البته با وجود تمام این موارد بدلیل رشد روز افزون استاندارد هایی مانند CORS و LINK Header بنظر می رسد دیگر نیازی به افزودن اینگونه فرا داده ها نباشد.

بنابراین شاید بهتر باشد بصورت پیشفرض اینگونه wrap کردن را در API خود غیر فعال کنیم و تنها در شرایطی خاص آن را اعمال کرده و کلاینت ارائه دهیم.

در دو شرایط ممکن است نیاز به wrap کردن پاسخ بصورت بالا باشد. یکی وقتی است که نیاز باشد درخواست های بین دامنه ای (cross domain requests) از طریق JSONP ارسال شود و یا اینکه امکان دسترسی و استفاده از هدر های HTTP برای کلاینت فراهم نباشد.

در خواست های JSONP معمولا بهمراه یک تابع callback ارسال می شوند. در چنین حالتی نیاز است پاسخ را بطور کامل wrap کنیم و همواره با  HTTP هدر 200 آن را بازگردانیم. توجه داشته باشید که کد وضعیت اصلی پاسخ یا HTTP Status Code باید در قسمت payload درخواست مشخص می شود. در زیر مثالی از اینگونه wrap کردن پاسخ آورده شده است :

 

callback_function({
  status_code: 200,
  next_page: "https://..",
  response: {
    ... actual JSON response body ... 
  }
})

در مورد آن دسته از کلاینت هایی که نمی توانند به هدر های HTTP دسترسی داشته باشند بهتر است بطور پیش فرض پاسخ ها بدون wrap کردن ارسال شوند ولی با پارامتری خاص مثلا envelope=true بتوان پاسخ را بصورت Wrap شده نیز برای کلاینت ها فراهم نمود.

 

 

صفحه بندی

سرویس هایی که پاسخ ها را wrap شده در اختیار کلاینت ها قرار می دهند، معمولا داده هایی در مورد صفحه بندی را نیز در قالب پاسخ باز می گردانند. در گذشته اینکار شاید منطقی بنظر می رسید چون راه دیگری برای این منظور وجود نداشت ام  امروزه با معرفی شدن Link Header بنظر می رسد دیگر نیازی به این کار دیگر نباشد.

سرویس هایی که از Link header استفاده می کنند می توانند مجموعه ای از لینک ها را به کلاینت بازگردانند. بنابراین کلاینت نیازی ندارد خودش لینک ها را تولید نماید. در ادامه مثالی از بکارگیری Link header آورده شده است که از مستندات GitHub گرفته شده است.

 

Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next", <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"

اما توجه داشته باشید که علاوه بر لینک های صفحه بندی، کلاینت ها معمولا نیاز به داده های دیگری نیز دارند. مثلا نیاز دارند بدانند تعداد کل نتایج چقدر است. اگر API ای نیاز به ارسال تعداد نتایج یافت شده داشت می توان از هدر هایی اختصاصی مثل X-Total-Count استفاده نماید.

بنابراین می بینید که نیازی به Wrap کردن داده ها وجود ندارد و میتوان انواع مختلفی از داده ها را از طریق هدر های HTTP ارسال نمود.

 

منبع : Best Practices for Designing a Pragmatic RESTful API

موفق و پیروز باشید

hamedkh
5.8 k     1     18     72
نظرات

عالی بود، ممنون از زحماتتون

مفید ومختصر... واقعا عالی بود. تشکر

عالی بود، ممنون از شما http://parsiprozhe.ir