مقدمه ای بر ساخت API با فریمورک hapi.js

13 خرداد 1398, خواندن در 9 دقیقه

در این آموزش قصد داریم علاوه بر شرح مقدمه ای در باب فریمورک hapi.js که بر پایه ی Node.js هست, یک پروژه ساده API هم بسازیم و شما میتونید از طریق این لیک به پروژه دسترسی داشته باشید. 

موضوعات

  • مقدمه ای بر hapi.js
  • نصب Node.js
  • نصب MySQL
  • راه اندازی اولیه ی پروژه
  • ساختار پوشه و فایل
  • API 
  • -سرور
  • -احراز هویت
  • -مسیریابی
  • -کنترلر و پلاگین های سرور
  • -مدل
  • -ارزیابی

مقدمه

hapi.js یک فریمورک قدرتمند متن باز هست که برپایه ی Node.js و برای ساخت اپلیکیشن ها و سرویس های وب, ساخته شده است. توسط Hammer ساخته شده و هم اکنون توسط معمار ارشد پلتفرم موبایل در کمپانی Walmart توسعه داده می شود. به همین خاطر مدیران این شرکت تصمیم گرفتند از فریمورک hapi.js برای بخش ظاهری معاملات تجاری کمپانی Walmart استفاده کنند.

در این مقاله  ما از یک پروژه ی متن باز به نام sample-hapi-rest-api استفاده خواهیم کرد.

نصب Node.js

اولین چیزی که ما احتیاج داریم اینه که Node.js رو نصب کنیم. Node.js یک پلتفرم برپایه ی جاوا اسکریپت زمان اجرای گوگل کروم هست و برای ساخت سریع, منعطق اپلیکیشن های شبکه استفاده می شود. Node..js از یک مدل I/O رویداد محور و غیرقابل بلاک استفاده میکنه که باعث میشه برای اپلیکیشن های بلادرنگی که در سراسر دستگاه های توزیع شده اجرا می شود, سبک تر, موثر تر و مناسب تر باشد. برای نصب Node.js یک تب ترمینال باز کرده و دستورات زیر رو وارد کنید :

sudo apt-get update
sudo apt-get install nodejs

نصب MySQL

در این پروژه ما از یک دیتابیس MySQL استفاده میکنیم اگر شما MySQL رو بصورت نصب شده در سیستم خودتون ندارید, با استفاده از دستورات زیر اون رو نصب کنید :

sudo apt-get update
sudo apt-get install mysql-server
sudo apt-get install mysql-client

در حین فرآیند نصب ممکنه لازم باشه که برای کاربر اصلی رمز عبور وارد کنید.

راه اندازی پروژه

خب حالا که ما Node.js و MySQL رو نصب کردیم, می خواهیم پروژه رو راه اندازی کنیم. در این پروژه شما میتونید یک API RESTful که از یک دیتابیس MySQL استفاده میکنه و توسط فریمورک hapi.js ساخته شده, بسازید. 

توضیحات زیر در صفحه ی خود پروژه هم مطرح شده است.

ساختار پوشه و فایل

برای شروع بخش های مهم ساختار بصورت زیر هست :

package.json
index.js
node_modules/
src/
|-config/
  |-constants.js
|-controllers/
|-dao/
|-middleware/
  |-basic-auth.js
  |-db.js
|-models/
|-routes/
|-util/
|-validate/
  • package.json : پیکربندی پروژه رو نگه می داره.
  • index.js : نقطه ی شروع برای API هست.
  • node_modules : تمام ماژول های توزیع شده در فایل package.json توسط دستورات npm و بصورت خودکار در این مسیر قرار خواهند گرفت. برای نمونه دستور npm install mysql --save
  • src : پوشه ی منبع کد پایه ی ماست.
  • src/config : فایل های پیکربندی در سطح اپلیکیشن اینجا قرار می گیرند.
  • src/config/constants.js : ثابت های پیکربندی در سطح اپلیکیشن هستند.
  • src/controller : فایل ها یا ماژول های کنترلر.
  • src/dao : فایل ها یا ماژول های آبجکت دسترسی اطلاعات.
  • src/middleware : فایل ها یا ماژول هایی رو نگه می داره که با محیط های مختلف کد سر و کار دارند.
  • src/middleware/basic-auth.js : ماژول اولیه برای استراتژی احراز هویت که بعدا شرح می دهیم.
  • src/middleware/db.js : انتصاب اولیه و تغییرات دیتابیس ما رو بر عهده داره.
  • src/models : فایل ها یا ماژول های انتصاب شمای دیتابیس ما.
  • src/routes : فایل ها یا ماژول هایی که می گویند چه کنترلری باید درخواست های ورودی رو مدیریت کنه.
  • src/util :  متد های mixin و کمکی رو برای ما فراهم می کند. 
  • src/validate : مسئول این هست که درخواست ورودی باید چه رفتاری داشته باشد.

API

در هر پروژه ی Node.js ما باید یک نقطه ی شروع داشته باشیم. در این پروژه نقطه ی شروع ما فایل index.js هست که بخش های اصلی اون شامل کد های زیر هست :

//1.
var Hapi = require('hapi');

//2.
var server = Hapi.createServer(host, port, options);

//3.
for (var route in routes) {
	server.route(routes[route]);
}

//4.
server.start();

انتصاب ماژول hapi.js به یک متغیر Hapi. ماژول در پوشه ی node_modules موجود هست پس نیازی نیست که ما یک مسیر برای اون تعیین کنیم.

  1. ساخت یک نمونه از سرور.
  2. به صورت داینامیک تمام مسیرها رو به نمونه ی سرور اضافه کردیم. مسیرها در پوشه ی src/routes ذخیره شده اند.

احراز هویت

این که یک API درخواست کلاینت رو در برابر گواهی نامه ها, ارزیابی کنه, کار معمولی هست. در این آموزش گواهی نامه ها به شکل آدرس ایمیل کاربر و رمز عبور اون که در دیتابیس و جدول user ما ذخیره شدند, خواهند بود. برای این بخش ما می خواهیم از ماژول hapi-auth-basic استفاده کنیم, پس وقتی کلاینت درخواستی رو ارسال میکنه, این مازول استراتژی احراز هویت رو مدیریت می کنه. کار روی فایل index.js رو ادامه می دهیم و ما hapi-auth-basic رو به پک سرور خودمون اضافه کردیم. پک سرور چندین سرور رو در یک پک واحد دسته بندی میکنه و با اون ها به عنوان یک موجود واحد رفتار میکنه که میتونه در یک همگام سازی شروع و پایان پیدا کنه, این کار بخوبی فعالسازی اشتراک مسیرها یا سایر عملیات ها مثل احراز هویت, انجام میشه. کد زیر در فایل index.js مسئول این وظیفه هست :

var basicAuth = require('src/middleware/basic-auth');
...
server.pack.require('hapi-auth-basic', function (err) {
	server.auth.strategy('simple', 'basic', true, {
		validateFunc: basicAuth
	});
});

توجه کنید که مدیر basicAuth یک ماژول یا تابع هست که در مسیر src/middleware/basic-auth ذخیره شده که ما برای ارزیابی گواهی درخواست ارسالی کاربر اون رو ساختیم.

این به دیتابیس رفته و دنبال کاربری با آدرس ایمیل و رمز عبور ارسالی می گرده.

شما میتونید با رفتن به مسیر localhost:8000/tasks اون رو تست کنید( البته اگر پیکربندی پورت رو عوض نکرده باشید) و بصورت زیر تایپ کنید :

Username: [email protected]
Password: 123

مسیریابی

مسیریابی با hapi.js بسیار کاربردی هست. نگاهی به فایل src/routes/task.js بیاندازید. شما می بینید که ما تمام مسیرها رو طوری پیکربندی کردیم که ماژول وظیفه لیستی از آبجکت های JSON رو احتیاج داره. اولین مسیر رو به عنوان مثال بیان می کنیم :

method: 'GET',
path: '/tasks/{task_id}',
config : {
	handler: taskController.findByID,
	validate: taskValidate.findByID
}
  • method : متد HTTP. معمولا یکی از GET,POST,PUT,... هست. هر متد HTTP قابل استفاده هست بجز HEAD.
  • path : مسیر مطلق برای تطبیق درخواست های ورودی استفاده میشه (باید با / شروع بشه) درخواست های ورودی با مسیرهای پیکربندی شده وابسته به آپشن های پیکربندی مسیر مقایسه می شوند. مسیر میتونه شامل پارامترهای اسم گذاری شده محصور در {} باشند که در برابر مقادیر لفظی در درخواست ها مطابقت داده می شوند.
  • config : پیکربندی اضافی مسیر ( آپشن های این مورد اجازه میده اطلاعات مسیر رو از پیاده سازیش تقسیم بندی کنیم).
  • config.handler : موقعیت اضافه برای تابع handler هست. مثل آپشن handler در سطح والدین. این میتونه برای هر مسیر یک handler رو قرار بده.
  • config.validate : برای ارزیابی درخواست های ورودی استفاده میشه. بعدا در موردش بیشتر صحبت خواهیم کرد.

کنترلر

ماژول های کنترلر برای میانجی گری بین درخواست ها و دستکاری اطلاعات, استفاده می شوند. فایل src/controllers/task.js رو باز کنید. ببینید که ما یک متد برای مدیریت هر مسیر درخواست توسط فایل src/routes/task اختصاص دادیم. هر ماژول کنترلر از یک ماژول کمکی به نام ReplyHelper استفاده می کنه. اینجا نکته اضافی درمورد hapi.js وجود نداره.

پلاگین های سرور

فایل src/controlers/task.js رو مجددا باز کنید و به این بخش نگاهی بیاندازید :

findByID: function findByID(request, reply) {

	var helper = new ReplyHelper(request, reply);
	var params = request.plugins.createControllerParams(request.params);

	taskDAO.findByID(params, function (err, data) {
		helper.replyFindOne(err, data);
	});
}

ببینید که ما متد createControllerParams رو از فضای request.plugins صدا می زنیم؟

پلاگین ها یک پلتفرم توسعه پذیر برای هر دو خدمات هدف دار عمومی مثل یک درخواست batch و برای منطق بیزینس اپلیکیشن فراهم می آورند.

این متد در فایل index.js به صورت زیر تعریف شده است :

server.ext('onRequest', function(request, next){
	request.plugins.createControllerParams = function(requestParams){
		var params = _.clone(requestParams);
		params.userId = request.auth.credentials.userId;
		return params;
	};
	next();
});

پس اساسا این یک راه بهتر برای بیان اینه که هر آبجکت درخواست باید قادر باشه شناسه ی کاربر احراز هویت شده رو به برخی آبجکت های requestParams اضافه کنه و اون رو به صدا زننده برگردونه. ما از این شناسه برای ایجاد تعدادی کوئری به MySQL استفاده خواهیم کرد.

مدل

از اونجایی که ما داریم یک API می سازیم تا از یک دیتابیس MySQL استفاده کنیم, ما نیاز به جایی داریم که شمای جداول دیتابیس رو در اون جا ذخیره کنیم. این مکان مورد نظر ماژول های مدل هستند. فایل src/models/task.js رو باز کرده و نگاهی بهش بیاندازید, ما مشاهده می کنیم که چطور مطمئن بشیم آبجکت های Task مقادیر درستی در پراپرتی ها دارند.

ارزیابی

اگر شما بخش قبلی رو مطالعه نکردید, فایل src/models/task.js رو باز کنید :

"use strict";

var _ = require('underscore');
var Joi = require('joi');

function TaskModel(){
	this.schema = {
		taskId: Joi.number().integer(),
		description: Joi.string().max(255)
	};
};

module.exports = TaskModel;

ما از ماژول Joi استفاده می کنیم. همین طور که در مستنداتش آمده, Joi یک زبان شرح شمای آبجکت و اعتبارسنج برای آبجکت های جاوا اسکریپت هست.

هر درخواستی که ما دریافت می کنیم در نهایت توسط Joi ارزیابی میشه. پس هر منبع یک ماژول  RewourceValidate  داره. به فایل src/validate/task.js نگاهی بیاندازید که یک شمای ارزیابی برای هر مسیر / متد / نقطه پایان تعریف میکنه.

دستکاری اطلاعات

یک مازول خوب وجود داره که برای دستکاری دیتابیس های MySQL ساخته شده. اسم اون node-mysql هست و ما ازش در پروژه مون استفاده کردیم.

اگر نگاهی به فایل src/dao/task.js بیاندازید, مشاهده می کنید که ما یک متد متناظر برای هر نقطه پایان که یک کلاینت میتونه درخواست کنه, داریم. 

نتیجه گیری

ما شروع به ساخت یک API برای وب سایت http://www.agendor.com.br کردیم. ما مثالی از ساختار فایل ها و پوشه ها, توسط فریمورک hapi.js که از دیتابیس MySQL استفاده کنه پیدا نکردیم. پس این مثال رو تهیه کردیم.

ما از دید یک نمونه افرادی که از PHP به Node.js کوچ کرده و از دیتابیس MySQL استفاده می کنند, آموزش ها رو دنبال می کنیم. امیدواریم که این پروژه نقطه شروع خوبی برای افرادی باشه که در این سناریو افتاده اند.

منابع مورد استفاده

Eran Hammer

Hapi, a prologue

agendor

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید