Maqaalkan wuxuu ku saabsan yahay mawduuc muhiim ah oo ku saabsan ganacsiga online-ka.
π Node.js in 2026: Node.js powers the backends of Netflix, LinkedIn, Uber, and PayPal. Its event-driven, non-blocking architecture handles thousands of simultaneous connections efficiently. With JavaScript on both frontend and backend, a single developer can build a complete application stack.
43%
Backend Devs Use Node.js
2M+
npm Packages Available
Netflix
Powers Streaming (Node.js)
1. REST API Fundamentals
REST (Representational State Transfer) is the architectural style that powers most web APIs. A REST API uses standard HTTP methods, stateless communication, and consistent URL structures to enable any client (browser, mobile app, another server) to communicate with your server.
HTTP Methods and Status Codes
| Method | Action | Example | Status |
|---|
| GET | Read data | GET /api/posts | 200 OK |
| POST | Create resource | POST /api/posts | 201 Created |
| PUT | Replace resource | PUT /api/posts/1 | 200 OK |
| PATCH | Partial update | PATCH /api/posts/1 | 200 OK |
| DELETE | Remove resource | DELETE /api/posts/1 | 204 No Content |
2. Express Setup: Production-Ready Configuration
mkdir my-api && cd my-api
npm init -y
npm install express cors helmet morgan dotenv
npm install bcryptjs jsonwebtoken joi
npm install @prisma/client
npm install -D nodemon prisma
# Add to package.json scripts:
# "start": "node server.js",
# "dev": "nodemon server.js"
// server.js β Complete, production-ready Express setup
const express = require("express");
const cors = require("cors");
const helmet = require("helmet");
const morgan = require("morgan");
require("dotenv").config();
const app = express();
// Security headers β always use helmet
app.use(helmet());
// CORS β restrict to your frontend domain
app.use(cors({
origin: process.env.CLIENT_URL || "http://localhost:3000",
credentials: true
}));
// Body parsing
app.use(express.json({ limit: "10mb" }));
app.use(express.urlencoded({ extended: true }));
// Request logging
if (process.env.NODE_ENV !== "test") {
app.use(morgan("dev"));
}
// Routes
app.use("/api/users", require("./routes/users"));
app.use("/api/auth", require("./routes/auth"));
app.use("/api/posts", require("./routes/posts"));
// Health check endpoint
app.get("/health", (req, res) => res.json({ status: "healthy", timestamp: new Date() }));
// 404 handler β must come after all routes
app.use("*", (req, res) => {
res.status(404).json({ error: "Route not found", path: req.originalUrl });
});
// Global error handler β must have 4 parameters
app.use((err, req, res, next) => {
const status = err.status || 500;
console.error(err.stack);
res.status(status).json({
error: process.env.NODE_ENV === "production" ? "Internal server error" : err.message
});
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
3. Route and Controller Pattern
// routes/posts.js β clean route definitions
const router = require("express").Router();
const postsController = require("../controllers/postsController");
const { authenticate } = require("../middleware/authenticate");
const { validate } = require("../middleware/validate");
const { postSchema } = require("../schemas/postSchema");
router.get("/", postsController.getAll);
router.get("/:id", postsController.getById);
router.post("/", authenticate, validate(postSchema), postsController.create);
router.put("/:id", authenticate, postsController.update);
router.delete("/:id", authenticate, postsController.remove);
module.exports = router;
// controllers/postsController.js β business logic
const prisma = require("../lib/prisma");
exports.getAll = async (req, res, next) => {
try {
const { page = 1, limit = 10, search } = req.query;
const where = search ? { title: { contains: search, mode: "insensitive" } } : {};
const skip = (parseInt(page) - 1) * parseInt(limit);
const [posts, total] = await Promise.all([
prisma.post.findMany({
where,
include: { author: { select: { id: true, name: true } } },
orderBy: { createdAt: "desc" },
skip,
take: parseInt(limit)
}),
prisma.post.count({ where })
]);
res.json({
data: posts,
pagination: { total, page: parseInt(page), pages: Math.ceil(total / limit) }
});
} catch (err) { next(err); }
};
4. Input Validation
const Joi = require("joi");
// Schema for creating a post
exports.postSchema = Joi.object({
title: Joi.string().min(3).max(200).required(),
content: Joi.string().min(10).required(),
category: Joi.string().valid("tech", "business", "health", "other").required(),
tags: Joi.array().items(Joi.string()).max(5).optional(),
published: Joi.boolean().default(false)
});
// Validation middleware factory
exports.validate = (schema) => (req, res, next) => {
const { error, value } = schema.validate(req.body, {
abortEarly: false, // Return ALL validation errors at once
stripUnknown: true // Remove unrecognized fields
});
if (error) {
const errors = error.details.map(d => ({
field: d.path.join("."),
message: d.message.replace(/"/g, "")
}));
return res.status(422).json({
error: "Validation failed",
details: errors
});
}
req.body = value; // Use cleaned and validated data
next();
};
5. Rate Limiting and Security
const rateLimit = require("express-rate-limit");
// Different limits for different endpoints
const generalLimit = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests
standardHeaders: true,
message: { error: "Too many requests" }
});
const authLimit = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // Only 5 login attempts
message: { error: "Too many login attempts, try again in 15 minutes" }
});
// Apply to specific routes
app.use("/api/", generalLimit);
app.use("/api/auth/login", authLimit);
app.use("/api/auth/register", authLimit);
// Security checklist:
// Use HTTPS (enforce at load balancer/Nginx level)
// Store passwords with bcrypt (cost factor 12+)
// Keep ALL secrets in environment variables
// Set CORS to specific origins, never "*"
// Sanitize and validate ALL user input
// Use parameterized queries (ORM handles this)
// Set security headers with Helmet
6. Complete JWT Authentication System
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");
// Register new user
exports.register = async (req, res, next) => {
try {
const { name, email, password } = req.body;
// Hash password (cost factor 12 = ~300ms, safe for 2026 hardware)
const hashedPassword = await bcrypt.hash(password, 12);
const user = await prisma.user.create({
data: { name, email, password: hashedPassword }
});
const token = generateToken(user);
const { password: _, ...safeUser } = user;
res.status(201).json({ token, user: safeUser });
} catch (err) {
if (err.code === "P2002") { // Prisma unique constraint violation
return res.status(409).json({ error: "Email already registered" });
}
next(err);
}
};
// Login
exports.login = async (req, res, next) => {
try {
const { email, password } = req.body;
const user = await prisma.user.findUnique({ where: { email } });
// Always compare hash (prevent timing attacks)
const validPassword = user && await bcrypt.compare(password, user.password);
if (!validPassword) {
return res.status(401).json({ error: "Invalid email or password" });
}
const token = generateToken(user);
const { password: _, ...safeUser } = user;
res.json({ token, user: safeUser });
} catch (err) { next(err); }
};
function generateToken(user) {
return jwt.sign(
{ id: user.id, email: user.email, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: process.env.JWT_EXPIRES_IN || "7d" }
);
}
7. Deploying Your API
π
Railway
Best for full-stack apps. Handles Node.js, PostgreSQL, Redis on one platform. Free tier included.
Easiest Setuprailway.appπ
Render
Free Node.js web services and PostgreSQL. Auto-deploys from GitHub. Good for solo developers.
Free Tierrender.comβοΈ
AWS / GCP
Production-grade cloud. EC2, Lambda (serverless), Cloud Run. More complex but infinitely scalable.
Production ScaleIndustry Standard
π― REST API Best Practices
- Use proper HTTP methods and status codes consistently across all endpoints
- Validate and sanitize ALL user input β never trust client-submitted data
- Never expose passwords, tokens, or sensitive data in API responses
- Implement rate limiting on public endpoints from day one
- Use environment variables for all secrets and configuration
- Structure code with separate routes, controllers, and middleware
- Document your API β Swagger/OpenAPI makes it professional and usable
</div>
π¬ Faallada iyo Su'aalaha
Su'aal ma qabtaa? Wax ka qor hoose β waxaan kuu jawaabi doonaa sida ugu dhaqsaha badan. Faalladaada muhiim ayay noogu tahay!