Simple Server on node.js and express Crud in Bangla ⇾ Explain Backend Series
Basic Backend Part 1
যখন আমরা ব্যাকএন্ড সার্ভার এপ্লিকেশন এর কথা চিন্তা করি এবং তা তৈরী করি সেখানে সার্ভার এপ্লিকেশন এর রেস্পন্সিবিলিটি কে ৩ তা ভাগে ভাগ করা যেতে পারে । সকল ব্যাকএন্ড ডেভেলপমেন্ট ঠিক একই প্রসেস এ কাজ করে থাকে ।
Server Application Responsibility:
- Listen to Request
- Process To Request
- Response back
Create Manual-Server In Node.js
একটি মেনুয়াল নোড js সার্ভার তৈরির মাধ্যমে আমরা তা এক্সপ্লেইন করতে পারি :
const http = require("http");
const server = http.createServer((req,res)=>{
if(req.url==='/'){
res.write('<h1>Hello World</h1>');
res.statusCode =200;
res.end();
}else{
res.write('<h1>404 page not found</h1>');
res.statusCode= 200;
res.end();
}
})
server.listen(8000,()=>{
console.log('Server is running on port 8000')
})
উপরের কোড ব্লক এ একটি সিম্পল নোড js সার্ভার রান করা হয়েছে ।
const http = require("http");
নোড js এর http মডিউল কে require করে নিয়ে আসা হয়েছে যার কাজ একটি http সার্ভার তৈরী করা ও তাকে সার্ভ করা ।
Process request
const server = http.createServer((req,res)=>{ if(req.url==='/'){ res.write('<h1>Hello World</h1>'); res.statusCode =200; res.end(); }else{ res.write('<h1>404 page not found</h1>'); res.statusCode= 200; res.end(); } })
http মডিউল কে ব্যবহার করে একটি রিকোয়েস্ট কে প্রসেস করা হয়েছে
if(req.url==='/'){ res.write('<h1>Hello World</h1>');
। user কি চাচ্ছে তার উপর ভিত্তি করে একটি রিকোয়েস্ট কে প্রসেস করা হয়ে থাকে ।Response Back
res.end()
এই ফাঙ্কশন টি কল করার মাধ্যমে response ব্যাক দেয়া হয়েছে ।Listen Server
server.listen(8000,()=>{ console.log('Server is running on port 8000') }
একটি সার্ভার তার কোন পোর্ট কে ব্যবহার করে রিকোয়েস্ট একসেপ্ট করবে তা
server.listen()
ফাঙ্কশন এর প্রথম আর্গুমেন্ট এ বলা হয় ,এক্ষেত্রে আমরা পোর্ট ৮০০০ ব্যবহার করেছি । ২য় আর্গুমেন্ট একটি কলব্যাক ফাঙ্কশন নিয়ে থাকে এবং একটি মেসেজ ব্যাক করে ।তাহলে আমরা বুজতে পারলাম একটি বেসিক সার্ভার রান করতে ৩টি প্রসেস যথেষ্ট এবং এখানে listen request alwys same থাকবে । response back করার ক্ষেত্রে সবসময় একই প্রসেস থাকবে । তবে request process করার ক্ষেত্রে algorithms,Data Structure,Database,problem solving,CRUD oparation এর মতো প্রোগ্রামিং জ্ঞান কে কাজে লাগিয়ে ব্যাকএন্ড এপ্লিকেশন create হয় ।
Making crud operation and server in express.js
node js এর সবথেকে পপুলার ফ্রেমওয়ার্ক এর কথা বলতে গেলে সবার উপরে যে নাম টি চলে আসবে তা হলো express.js ।খুব ছোট একটি ফ্রেমওয়ার্ক কিন্তু খুব powerful এই ফ্রেমওয়ার্কটি ।আমাদের পরবর্তী গোল এক্সপ্রেস ব্যবহার করে simple একটি node js এপ্লিকেশন বানানো । যা crud অপারেশন চালাতে পারবে ।
Setup environment and folder:
কম্পিউটার এ যে কোনো জায়গায় একটি ফোল্ডার তৈরী করে তা visual studio
কোড এ ওপেন করতে হবে ।সেক্ষেত্রে আমি আমার ফোল্ডার এর নাম দিচ্ছি basicExpress
। ভিজ্যুয়াল ষ্টুডিও কোড টার্মিনাল এ npm init -y
commend টি চালালে একটি package.json
file তৈরী হবে ।এরপরে server.js
নামে একটি ফাইল basicExpress ফোল্ডার এ তৈরী করবো ।
npm i express
terminal এ উপরের কমান্ড টি রান করলে basicExpress প্রজেক্ট টির জন্য এক্সপ্রেস ফ্রেমওয়ার্কটি ইনস্টল হয়ে যাবে । পরবর্তীতে যে কোনো ফাইল এ require করে ব্যবহার করতে পারবো।package.json
ফাইল টি ওপেন করলে ডিপেন্ডেন্সির মধ্যে সকল ইনস্টল করা প্যাকেজ দেখতে পাবো (যদি সঠিক ভাবে ইনস্টল হয় )যার মধ্যে express আছে ।
install nodemon :
nodemon হচ্ছে অটোমেটিক্যালি নোড সার্ভার রান করার একটি টুলস যা ফাইল চেঞ্জ করলে ইনস্ট্যান্ড সার্ভারে সার্ভ করে ।
npm i -D nodemon
উপরের কমান্ড রান করলে dev ডিপেন্ডেন্সিতে nodemon যোগ হয়ে যাবে এবং package.js
এ একটি স্ক্রিপ্ট লিখতে হবে নোড মন রান করার জন্য ।
"scripts":{
"start":"nodemon server.js"
}
npm run start
কমান্ড টি টার্মিনাল এ চালালে server.js
ফাইল টি সার্ভ করা স্টার্ট করবে ।
Start Writing Code for Express:
server.js
ফাইল এর মধ্যে প্রথমেই কমন js মডিউল স্টাইল ফলো করে express require করে নিয়ে আসব ।
const express = require('express')
const app = express()
express ভ্যারিয়েবল টি app তৈরী করে ।
একটি ব্যাকএন্ড এপ্লিকেশন এর প্রথম কাজ একটি সার্ভার তৈরী করা যে listen করতে পারবে ।
app.listen(8000,()=>{
console.log("server is listening on port 8000")
})
app.listen() একটি ফাঙ্কশন যা কিনা ফার্স্ট আর্গুমেন্ট এ দেয়া স্পেসিফিক পোর্ট এ সার্ভার কে রান করে রাখে । আর এর সেকেন্ড আর্গুমেন্ট একটি কলব্যাক ফাঙ্কশন provide করে ।
এখন পর্যন্ত server.js
file er final code :
const express = require('express')
const app = express()
app.listen(8000,()=>{
console.log("server is Listening on port 8000")
})
HTTP For Routing:
http এর ফুলফর্ম hypar text transfer protocol । সার্ভার এবং ক্লায়েন্ট এর সাথে যোগাযোগ স্থাপন করায় যে প্রোটোকল ব্যবহার করাহয় তাই http। http টেক্সট আকারে ক্লায়েন্ট ও সার্ভার এর মধ্যে কোমোনিকেশন করেথাকে । এই কোমিনিকেশন সিস্টেম স্টেটলেস হয় ।
Stateless communication : ক্লায়েন্টস রিকোয়েস্ট পাঠাবে সার্ভার সেখানে রেসপন্স ব্যাক করবে then সার্ভার close হয়ে যাবে । এই যে সার্ভার এর সাথে ক্লায়েন্টস এর কানেকশন close হলো এটাকেই মূলত Stateless communication ।
HTTP মূলত ৫ টা উপায়ে কাজ করে থাকে । এর বাইরেও অনেকগুলো মেথড বা উপায় রয়েছে কিন্তু উল্লেখযোগ্য ৫টি । আমরা যে crud অপারেশন চালায়, সেই crud এর পাঁচ কন্সেপ নিয়েই http রিকোয়েস্ট মেথড কাজ করে ।
HTTP request method :
- GET (সার্ভার থেকে ডাটা read করার জন্য )
- POST (নতুন ডাটা তৈরী করার জন্য )
- PUT / PATCH (এক্সজেস্টিং ডাটা আপডেট করার জন্য )
- DELETE (ডাটা ডিলিট করার জন্য )
এছাড়াও অনেক http রিকোয়েস্ট রয়েছে তবে তা তুলনা মূলক কম ব্যবহার হয়ে থাকে।এই সকল রিকোয়েস্ট গুলো ক্লায়েন্ট থেকে আসবে আর এখানে ক্লায়েন্ট বলতে ডিভাইস গুলোকে বোঝানো হয়েছে যেমন মোবাইল ,কম্পিউটার ব্রাউজার ,ট্যাবলেট ইত্যাদি । ক্লায়েন্ট যে কোনো সময় যেকোনো ভাবে রিকোয়েস্ট পাঠাতে পারে get,post কিংবা delete । ডেভেলপারদের responsibility হচ্ছে রিকোস্ট অনুযায়ী ব্যাকএন্ড এ ডাটা হ্যান্ডেল করা ।
Back to code :
যথেষ্ট থিওরি হয়েছে কোড এ back করাযাক ।
server.js
ফাইল এ আমরা একটি গেট রিকোয়েস্ট হ্যান্ডেল করতে যাচ্ছি
const express = require('express')
const app = express()
app.get('/',(req,res)=>{
})
app.listen(8000,()=>{
console.log("server is listening on port 8000")
})
এখানে আমরা একটি get রিকোয়েস্ট হ্যান্ডেল করেছি app.get()
মেথড এর মাধ্যমে যা এক্সপ্রেস অবজেক্ট আমাদেরকে provide করে থাকে।
প্রত্যেকটি individual request এর একটা unique path বা route থাকতে হবে ।উদহারণ টেনে বলাযায় app.get('/') এখানে
'/'
হচ্ছে home route এছাড়া'/book '
,'/admin '
এগুলো সব আলাদা আলাদা route বা path হতে পারে এবং এর মেথড ব্যবহার ভেদে আলাদা হতে পারে যেমন get,post,delete কিংবা put।
app.get('/',(req,res)=>{
//Process Request
// Response Generator
})
app.method(get,post,put,delete) মেথড অনেক গুলো আর্গুমেন্ট নিতে পারে তবে, প্রথম আর্গুমেন্ট হিসেবে path/ route ও ২য় আর্গুমেন্ট এ handler বা callback ফাঙ্কশন নিয়ে থাকে।এই handler মূলত response generate করতে ব্যবহার হয় ।একজন ডেভেলপার শুধু ফাঙ্কশন তৈরী করবে ফাঙ্কশন কল করবে না। ফাঙ্কশন কল express নিজে থেকেই করে নিবে ।ডেভেলপার তার path / route এর উপর ভিত্তি করে রিকোয়েস্ট কে প্রোসেস করবে এবং রেসপন্স রিটার্ন করবে ।
Request and Response :
request কে শর্ট করে আমরা req এবং response কে শর্ট করে res বলতেপারি ।এ দুটি মূলত অবজেক্ট।এই req এবং res এর অসংখ প্রপার্টিস রয়েছে (resource) যেগুলো কে ব্যবহার করে request নেয়া হয় এবং response ব্যাক দেয়া হয় ।কিছু কোড এর উদহারণ দিয়ে বোঝানোর চেষ্টা করছি :
const express = require("express");
const app = express();
const books = [
{
id: "1",
name: "The Book Of Nothing",
price: 600,
},
{
id: "2",
name: "The Alchemists",
price: 800,
},
{
id: "3",
name: "A Big Zero",
price: 1600,
},
];
app.get("/books", (req, res) => {
res.json(books);
});
app.listen(8000, () => {
console.log("Server is Listening on Port 8000");
});
উপরে বুক নামে একটি InMemory ডেটাবেস বা array server.js
ফাইলে নিয়েছি যার মধ্যে অবজেক্ট আকারে অনেক গুলো বইয়ের name ,idও price দেয়া আছে ।এখন ক্লায়েন্ট যদি /books
route এ রিকোয়েস্ট করে তবে json ফরমেটে তাকে সব গুলো বই response ব্যাক করে দেয়া হবে।
Output http://localhost:8000/books
:
app.get("/books", (req, res) => {
res.json(books);
});
res.json
বিল্টইন ভাবে node.js এ থাকে না এক্সপ্রেস আমাদের হেল্প করছে respons এর json ফাঙ্কশন দিয়ে।
Filter Data:
আমরা এখন ফিল্টারিং করে বের করার চেষ্টা করবো যে বইগুলো ১০০ টাকার নিচে রয়েছে :
const express = require("express");
const app = express();
const books = [
{
id: "1",
name: "The Book Of Nothing",
price: 600,
},
{
id: "2",
name: "The Alchemists",
price: 800,
},
{
id: "3",
name: "A Big Zero",
price: 1600,
},
{
id: "4",
name: "The Phenix",
price: 100,
},
{
id: "5",
name: "A Jungle Flail",
price: 90,
},
];
app.get("/books", (req, res) => {
const result = books.filter((book) => book.price <= 100);
res.json(result);
});
app.listen(8000, () => {
console.log("Server is Listening on Port 8000");
});
array filter মেথড ব্যবহার করে আমরা ১০০ টাকার নিচে যে বই গুলো রয়েছে তা result এ store করছি এবং json ফরম্যাটে response ব্যাক দিচ্ছি ।
Output http://localhost:8000/books
:
Query Strings:
কিন্তু যদি এখন আমার দরকার হয় যে বই গুলো ২০০ টাকার উপরে আছে বা সব গুলো বই দরকার তাহলে আবার কোড করে প্রসেস করতে হবে।ক্লায়েন্ট চাইলেই তার রিকোয়েস্ট ডিনামিকলী দিতেপারছে না। এই প্রব্লেম solve করার জন্য query perams বা query strings এসেছে ।
http://localhost:8000/books?show=200
এই query string লেখার জন্য ?
মার্ক ব্যবহার করা হয় এর পরে নাম provide করে =
sign ব্যবহার করে স্ট্রিং pass করা হয় like ?id=3
app.get("/books", (req, res) => {
const query = req.query.show;
if (query == "all") {
return res.json(books);
}
const result = books.filter((book) => book.price <= 200);
res.json(result);
});
request অবজেক্ট এর মধ্যে query নামে একটি প্রপার্টি আছে যা
req.query
দিয়ে access করতে পারি এবং এটি একটি অবজেক্ট রিটার্ন করবে । এরপরে যদি.
দিয়ে query string এ provide করা নাম mansion করি তবে specific স্ট্রিং পাওয়া যাবে।
এখন আমরা যদি http://localhost:8000/books
query স্ট্রিং ছাড়া ব্রাউস করি তবে
const result = books.filter((book) => book.price <= 200);
res.json(result);
উপরের কোড এক্সিকিউট হবে এবং রেসপন্স হিসেবে ২০০ বা তার নিচের বইগুলো পাবো।
আর query string দিয়ে http://localhost:8000/books?show=all
দিয়ে ব্রাউস করি তবে
if (query == "all") {
return res.json(books);
}
উপরের কন্ডিশন রান করবে আর সব গুলো বই রেসপন্স ব্যাক করবে।
আমরা req এবং res অবজেক্ট বের করে এনে লজিক ব্যবহার করে ডাটা প্রসেস করতে পারি আবার সেই ডাটা ব্রাউজার্ এ ক্লায়েন্ট কে ব্যাক ও দিতে পারি।
Routing Patterns :
রাউটিং প্যাটার্ন্স মানে হচ্ছে যে patterns ব্যবহার করে api routing করা হয়।
GET Routing
get রাউটিং দুই ভাবে করাযায় । ধরাযাক আমরা সমস্ত রিসোর্স বা বুক একবারে পেতেচাই তাহলে রাউটিং টা হবে
/books
। আবার যদি সিঙ্গেল রিসোর্স বা book পেতেচাই তবে রাউটিং হবে/books/bookId
।POST Routing
post রাউটিং ও দুই টি ভার্শন । আমরা সমস্ত নতুন রিসোর্স বা বুক একবারে পেতেচাইলে তাহলে রাউটিং টা হবে
/books
। আবার যদি সিঙ্গেল রিসোর্স বা book পেতেচাই তবে রাউটিং হবে/books/bookId
।PUT/PATCH Routing
update যেহেতু আমরা একটা রিসোর্স বা book কে করেথাকি তাই এর রাউটিং হবে
/books/bookId
। তবে অনেক গুলো update একবারে করতেচাইলে/books
দিতে পারি ।DELETE Routing
delete যেহেতু আমরা একটা রিসোর্স বা book কে করেথাকি তাই এর রাউটিং হবে
/books/bookId
।
routing দুই ভাবে আলাদা করা হয় , path name এবং method দিয়ে ।রাউটিং path
/books,/books/bookId
যদি same হয় তবে তাদের mathodget,post,put,delete
এর উপর ভিত্তি করে unique route ধরা হয়।
Using Testing Tools
আমাদের ব্রাউজার শুধুমাত্র get রিকোয়েস্ট পাঠাতে পারে । আমরা চাইলেই Browser ব্যবহার করে post ,put বা delete রিকোয়েস্ট পাঠাতে পারবোনা । কোড করে পাঠাতে পারবো but আমরা চাচ্ছি ব্রাউসার বা ক্লায়েন্ট পাঠাক । আর এই প্রব্লেম solve করার জন্য api request sender টুলস ব্যবহার করবো ।অনেক গুলো টুলস রয়েছে রিকোয়েস্ট send করা বা অটোমেশন করার তবে populer হচ্ছে postman ,insomnia দুটোর কাজ একই আপনি চাইলে ডকুমেন্টেশন দেখে নিতে পারেন। তবে আমি insomnia ব্যবহার করছি ।
POST REQUEST
api ডিসাইন এর ক্ষেত্রে যে কয়টি মেথড বা request রয়েছে post রিকোয়েস্ট ব্যবহার করাহয় নতুন ডাটা তৈরী করার জন্য। আমরা post রিকোয়েস্ট এ জাভাস্ক্রিপ্ট object বা json object পাঠিয়ে থাকি ডাটাবেস এ save করে রাখার জন্য ।
- insomnia ব্যবহার করে post রিকোয়েস্ট পাঠাতেপারি
- create Post ডাটা insomnia tools
server.js
ফাইল :
const express = require("express");
const app = express();
app.use(express.json());
const books = [
{
id: "1",
name: "The Book Of Nothing",
price: 600,
},
{
id: "2",
name: "The Alchemists",
price: 800,
},
{
id: "3",
name: "A Big Zero",
price: 1600,
},
{
id: "4",
name: "The Phenix",
price: 100,
},
{
id: "5",
name: "A Jungle Flail",
price: 90,
},
];
app.get("/books", (req, res) => {
const query = req.query.show;
if (req.query.show == "all") {
return res.json(books);
}
const result = books.filter((book) => book.price <= 200);
res.json(result);
});
app.post("/books", (req, res) => {
console.log(req.body);
res.send("back to post request");
});
app.listen(8000, () => {
console.log("Server is Listening on Port 8000");
});
আমরা server.js
এ একটি post request উপরের উল্লেখিত syntex এ লিখেছি । path name এবং handler ফাঙ্কশন এ req ,res। একটি post request এ যে প্রসেস টা কমন তা হল ,ক্লায়েন্ট অবশ্যই কিছু ডাটা json অবজেক্ট আকারে backend এ পাঠাবে। ক্লায়েন্ট যেসব ডাটা json আকারে পাঠাবে তা req অবজেক্ট এর body নামক property এর মধ্যে পাওয়া যাবে । যেহেতু ক্লায়েন্ট json আকারে ডাটা send করেছে তাই আমাদের express এর provide করা app.use(express.json())
middleware ব্যবহার করতে হবে json কে জাভাস্ক্রিপ্ট অবজেক্ট এ পার্স করতে । অন্যথায় output undifined দেখাবে।
(middleware নিয়ে পরবর্তীতে বিস্তারিত আলোচনা করা হবে )
Terminal Output :
Server is Listening on Port 8000
{ id: '5', name: 'new book', price: 500 }
আমরা দেখতে পাচ্ছি যে ডাটা বা new book আমরা ক্লায়েন্ট থেকে পাঠিয়েছিলাম তা টার্মিনালে console log হয়ে আউটপুট দিয়েছে ।
যখন আমরা কোন route create করবো অবশ্যই সেই route এর response back করতে হবে। response back না করলে সার্ভার হ্যাং হয়ে ঘুরতে থাকবে ।
Save data on inMemory Database:
app.post("/books", (req, res) => {
books.push(req.body);
res.send(books);
});
আমরা req.body
প্রোপার্টিতে new book ডাটা পেয়েছি তাই books.push(req.body)
মেথড ব্যবহার করে books নামের inMemory Database এ save করে দিতে পারি । এবং রেসপন্স back করে res.send(books)
দিতে পারি।
insomnia Output :
নতুন দেয়া ডাটা books এ লাস্ট এ save হয়ে গিয়াছে । এখন ক্লায়েন্ট যতবার রিকোয়েস্ট পাঠাবে ততবার new book নামে ডাটা save হতে থাকবে ।আমরা চাইলেই এখন অনেক ধরণের validation ও নিজেদের মত লজিক লিখে data সেভ করতে পারি ।
PIPELINE
তাহলে আমরা যে পাইপলাইন বা প্রসেস ফলো করে ব্যাকএন্ড হানদের করতে পারি ছোট করে দেখলে সেটা দাঁড়ায় :
REQUEST -> MIDDLEWARE1,MIDDLEWARE2 -> CONTROLLER(Business logic) -> MIDDLEWARE(ERR HNDLER) -> RESPOSE
ঠিক এই প্রসাস ফলো করেই ব্যাকএন্ড লেখা হয়ে থাকে । আমরা পরবর্তী lesson এ মিডলওয়ার নিয়ে কাজ করবো