Express.js ilovalarida TypeScript middleware'ni tushunish va joriy etish bo'yicha keng qamrovli qo'llanma. Kuchli va qulay kod uchun ilg'or tur naqshlarini o'rganing.
TypeScript Middleware: Express Middleware Type Patternlarini O'zlashtirish
Express.js – minimalist va moslashuvchan Node.js veb ilovalari freymvorki boʻlib, dasturchilarga kuchli va kengaytiriladigan APIlar va veb ilovalar yaratish imkonini beradi. TypeScript statik turlashni qoʻshish, kodning qulayligini oshirish va xatolarni dastlabki bosqichlarda aniqlash orqali Express'ni takomillashtiradi. Middleware funksiyalari Express'ning asosiy toshi boʻlib, ular sizga soʻrovlarni marshrut ishlovchilaringizga yetib borguncha toʻxtatib, qayta ishlashga imkon beradi. Ushbu maqola Express middleware'ni aniqlash va undan foydalanish uchun ilgʻor TypeScript tur naqshlarini oʻrganadi, bu tur xavfsizligi va kodning aniqligini oshiradi.
Express Middleware'ni tushunish
Middleware funksiyalari soʻrov ob'ektiga (req), javob ob'ektiga (res) va ilovaning soʻrov-javob siklidagi keyingi middleware funksiyasiga kirish huquqiga ega boʻlgan funksiyalardir. Middleware funksiyalari quyidagi vazifalarni bajarishi mumkin:
- Istagan kodni bajarish.
- Soʻrov va javob ob'ektlariga oʻzgartirishlar kiritish.
- Soʻrov-javob siklini yakunlash.
- Stakdagi keyingi middleware funksiyasini chaqirish.
Middleware funksiyalari Express ilovasiga qoʻshilganidek, ketma-ket bajariladi. Middleware uchun umumiy foydalanish holatlari quyidagilarni oʻz ichiga oladi:
- Soʻrovlarni jurnalga yozish.
- Foydalanuvchilarni autentifikatsiya qilish.
- Resurslarga kirishni avtorizatsiya qilish.
- Soʻrov ma'lumotlarini tasdiqlash.
- Xatolarni boshqarish.
Asosiy TypeScript Middleware
Asosiy TypeScript Express ilovasida middleware funksiyasi quyidagicha koʻrinishi mumkin:
\nimport { Request, Response, NextFunction } from 'express';\n\nfunction loggerMiddleware(req: Request, res: Response, next: NextFunction) {\n console.log(`Request: ${req.method} ${req.url}`);\n next();\n}\n\nexport default loggerMiddleware;\n
Ushbu oddiy middleware soʻrov usulini va URL'ni konsolga yozadi. Keling, tur izohlarini koʻrib chiqaylik:
Request: Express soʻrov ob'ektini ifodalaydi.Response: Express javob ob'ektini ifodalaydi.NextFunction: ChaQirilganda stakdagi keyingi middleware'ni bajaradigan funksiya.
Ushbu middleware'ni Express ilovangizda quyidagicha ishlatishingiz mumkin:
\nimport express from 'express';\nimport loggerMiddleware from './middleware/loggerMiddleware';\n\nconst app = express();\nconst port = 3000;\n\napp.use(loggerMiddleware);\n\napp.get('/', (req, res) => {\n res.send('Salom, dunyo!');\n});\n\napp.listen(port, () => {\n console.log(`Server ${port} portida tinglamoqda`);\n});\n
Middleware uchun ilgʻor tur naqshlari
Asosiy middleware misoli funksional boʻlsa-da, murakkabroq stsenariylar uchun moslashuvchanlik va tur xavfsizligiga ega emas. Keling, TypeScript bilan middleware ishlab chiqishni takomillashtiradigan ilgʻor tur naqshlarini koʻrib chiqaylik.
1. Maxsus soʻrov/javob turlari
Koʻpincha, Request yoki Response ob'ektlarini maxsus xususiyatlar bilan kengaytirishga ehtiyoj tugʻiladi. Masalan, autentifikatsiyadan soʻng, Request ob'ektiga user xususiyatini qoʻshishni xohlashingiz mumkin. TypeScript sizga mavjud turlarni deklaratsiyani birlashtirish (declaration merging) orqali kengaytirish imkonini beradi.
\n// src/types/express/index.d.ts\nimport { Request as ExpressRequest } from 'express';\n\ndeclare global {\n namespace Express {\n interface Request {\n user?: {\n id: string;\n email: string;\n // ... other user properties\n };\n }\n }\n}\n\nexport {}; // This is needed to make the file a module\n
Ushbu misolda biz Express.Request interfeysini ixtiyoriy user xususiyatini oʻz ichiga olish uchun kengaytiryapmiz. Endi, autentifikatsiya middleware'ingizda ushbu xususiyatni toʻldirishingiz mumkin:
\nimport { Request, Response, NextFunction } from 'express';\n\nfunction authenticationMiddleware(req: Request, res: Response, next: NextFunction) {\n // Autentifikatsiya mantiqini simulyatsiya qilish\n const userId = req.headers['x-user-id'] as string; // Yoki tokendan olish, va hokazo.\n\n if (userId) {\n // Haqiqiy ilovada siz foydalanuvchini ma'lumotlar bazasidan olgan bo'lar edingiz\n req.user = {\n id: userId,\n email: `user${userId}@example.com`\n };\n next();\n } else {\n res.status(401).send('Ruxsat berilmagan');\n }\n}\n\nexport default authenticationMiddleware;\n
Va marshrut ishlovchilaringizda siz req.user xususiyatiga xavfsiz tarzda kirishingiz mumkin:
\nimport express from 'express';\nimport authenticationMiddleware from './middleware/authenticationMiddleware';\n\nconst app = express();\nconst port = 3000;\n\napp.use(authenticationMiddleware);\n\napp.get('/profile', (req: Request, res: Response) => {\n if (req.user) {\n res.send(`Salom, ${req.user.email}! Sizning foydalanuvchi ID'ingiz ${req.user.id}`);\n } else {\n // Agar middleware to'g'ri ishlayotgan bo'lsa, bu hech qachon sodir bo'lmasligi kerak\n res.status(500).send('Ichki server xatosi');\n }\n});\n\napp.listen(port, () => {\n console.log(`Server ${port} portida tinglamoqda`);\n});\n
2. Middleware Fabrikalari
Middleware fabrikalari middleware funksiyalarini qaytaradigan funksiyalardir. Ushbu naqsh middleware'ni aniq opsiyalar yoki bog'liqliklar bilan sozlash kerak bo'lganda foydalidir. Masalan, xabarlarni ma'lum bir faylga yozadigan loglash middleware'ini ko'rib chiqing:
\nimport { Request, Response, NextFunction } from 'express';\nimport fs from 'fs';\nimport path from 'path';\n\nfunction createLoggingMiddleware(logFilePath: string) {\n return (req: Request, res: Response, next: NextFunction) => {\n const logMessage = `[${new Date().toISOString()}] Request: ${req.method} ${req.url}\n`;\n fs.appendFile(logFilePath, logMessage, (err) => {\n if (err) {\n console.error('Jurnal fayliga yozishda xato:', err);\n }\n next();\n });\n };\n}\n\nexport default createLoggingMiddleware;\n
Ushbu middleware fabrikasini quyidagicha ishlatishingiz mumkin:
\nimport express from 'express';\nimport createLoggingMiddleware from './middleware/loggingMiddleware';\n\nconst app = express();\nconst port = 3000;\n\nconst logFilePath = path.join(__dirname, 'logs', 'requests.log');\napp.use(createLoggingMiddleware(logFilePath));\n\napp.get('/', (req, res) => {\n res.send('Salom, dunyo!');\n});\n\napp.listen(port, () => {\n console.log(`Server ${port} portida tinglamoqda`);\n});\n
3. Asinxron Middleware
Middleware funksiyalari koʻpincha asinxron operatsiyalarni, masalan, ma'lumotlar bazasi soʻrovlarini yoki API chaqiruvlarini bajarishi kerak boʻladi. Asinxron operatsiyalarni toʻgʻri boshqarish uchun next funksiyasi asinxron operatsiya tugagandan soʻng chaqirilishini ta'minlashingiz kerak. Buni async/await yoki Promises yordamida amalga oshirishingiz mumkin.
\nimport { Request, Response, NextFunction } from 'express';\n\nasync function asyncMiddleware(req: Request, res: Response, next: NextFunction) {\n try {\n // Asinxron operatsiyani simulyatsiya qilish\n await new Promise(resolve => setTimeout(resolve, 100));\n console.log('Asinxron operatsiya yakunlandi');\n next();\n } catch (error) {\n next(error); // Xatolikni xatolarni boshqarish middleware'iga uzatish\n }\n}\n\nexport default asyncMiddleware;\n
Muhim: Asinxron middleware'ingizdagi xatolarni boshqarishni va ularni next(error) yordamida xatolarni boshqarish middleware'iga uzatishni unutmang. Bu xatolar toʻgʻri boshqarilishini va jurnalga yozilishini ta'minlaydi.
4. Xatolarni boshqarish Middleware'i
Xatolarni boshqarish middleware'i soʻrov-javob sikli davomida yuzaga keladigan xatolarni boshqaradigan maxsus turdagi middleware'dir. Xatolarni boshqarish middleware funksiyalari toʻrtta argumentga ega: err, req, res va next.
\nimport { Request, Response, NextFunction } from 'express';\n\nfunction errorHandler(err: any, req: Request, res: Response, next: NextFunction) {\n console.error(err.stack);\n res.status(500).send('Nimadir xato ketdi!');\n}\n\nexport default errorHandler;\n
Xatolarni boshqarish middleware'ini barcha boshqa middleware va marshrut ishlovchilardan keyin roʻyxatdan oʻtkazishingiz kerak. Express xatolarni boshqarish middleware'ini toʻrtta argumentning mavjudligi bilan aniqlaydi.
\nimport express from 'express';\nimport asyncMiddleware from './middleware/asyncMiddleware';\nimport errorHandler from './middleware/errorHandler';\n\nconst app = express();\nconst port = 3000;\n\napp.use(asyncMiddleware);\n\napp.get('/', (req, res) => {\n throw new Error('Simulyatsiya qilingan xato!'); // Xatoni simulyatsiya qilish\n});\n\napp.use(errorHandler); // Xatolarni boshqarish middleware'i oxirida ro'yxatdan o'tishi SHART\n\napp.listen(port, () => {\n console.log(`Server ${port} portida tinglamoqda`);\n});\n
5. Soʻrovlarni tasdiqlash Middleware'i
Soʻrovlarni tasdiqlash xavfsiz va ishonchli APIlar yaratishning muhim jihati hisoblanadi. Middleware kelayotgan soʻrov ma'lumotlarini tasdiqlash va ular marshrut ishlovchilaringizga yetib borguncha ma'lum mezonlarga mos kelishini ta'minlash uchun ishlatilishi mumkin. joi yoki express-validator kabi kutubxonalar soʻrovlarni tasdiqlash uchun ishlatilishi mumkin.
express-validator yordamida misol:
\nimport { Request, Response, NextFunction } from 'express';\nimport { body, validationResult } from 'express-validator';\n\nconst validateCreateUserRequest = [\n body('email').isEmail().normalizeEmail(),\n body('password').isLength({ min: 8 }),\n (req: Request, res: Response, next: NextFunction) => {\n const errors = validationResult(req);\n if (!errors.isEmpty()) {\n return res.status(400).json({ errors: errors.array() });\n }\n next();\n }\n];\n\nexport default validateCreateUserRequest;\n
Ushbu middleware soʻrov tanasidagi email va password maydonlarini tasdiqlaydi. Agar tasdiqlash muvaffaqiyatsiz tugasa, u xato xabarlari massivi bilan 400 Bad Request javobini qaytaradi. Siz ushbu middleware'ni marshrut ishlovchilaringizda quyidagicha ishlatishingiz mumkin:
\nimport express from 'express';\nimport validateCreateUserRequest from './middleware/validateCreateUserRequest';\n\nconst app = express();\nconst port = 3000;\n\napp.post('/users', validateCreateUserRequest, (req, res) => {\n // Agar tasdiqlash o'tsa, foydalanuvchini yarating\n res.send('Foydalanuvchi muvaffaqiyatli yaratildi!');\n});\n\napp.listen(port, () => {\n console.log(`Server ${port} portida tinglamoqda`);\n});\n
6. Middleware uchun bogʻliqliklarni kiritish (Dependency Injection)
Middleware funksiyalaringiz tashqi xizmatlarga yoki konfiguratsiyalarga bogʻliq boʻlganda, bogʻliqliklarni kiritish (dependency injection) sinovdan oʻtkazish qulayligini va saqlanishini yaxshilashga yordam beradi. Siz tsyringe kabi bogʻliqliklarni kiritish konteyneridan foydalanishingiz yoki shunchaki bogʻliqliklarni middleware fabrikalaringizga argument sifatida uzatishingiz mumkin.
Bogʻliqliklarni kiritish bilan middleware fabrikasidan foydalanish misoli:
\n// src/services/UserService.ts\nexport class UserService {\n async createUser(email: string, password: string): Promise {\n // Haqiqiy ilovada siz foydalanuvchini ma'lumotlar bazasiga saqlagan bo'lar edingiz\n console.log(`Foydalanuvchi ${email} elektron pochta manzili va ${password} paroli bilan yaratilmoqda`);\n await new Promise(resolve => setTimeout(resolve, 500)); // Ma'lumotlar bazasi operatsiyasini simulyatsiya qilish\n }\n}\n
\n// src/middleware/createUserMiddleware.ts\nimport { Request, Response, NextFunction } from 'express';\nimport { UserService } from '../services/UserService';\n\nfunction createCreateUserMiddleware(userService: UserService) {\n return async (req: Request, res: Response, next: NextFunction) => {\n try {\n const { email, password } = req.body;\n await userService.createUser(email, password);\n res.status(201).send('Foydalanuvchi muvaffaqiyatli yaratildi!');\n } catch (error) {\n next(error);\n }\n };\n}\n\nexport default createCreateUserMiddleware;\n
\n// src/app.ts\nimport express from 'express';\nimport createCreateUserMiddleware from './middleware/createUserMiddleware';\nimport { UserService } from './services/UserService';\nimport errorHandler from './middleware/errorHandler';\n\nconst app = express();\nconst port = 3000;\n\napp.use(express.json()); // JSON so'rov tanalarini tahlil qilish\n\nconst userService = new UserService();\nconst createUserMiddleware = createCreateUserMiddleware(userService);\n\napp.post('/users', createUserMiddleware);\n\napp.use(errorHandler);\n\napp.listen(port, () => {\n console.log(`Server ${port} portida tinglamoqda`);\n});\n
TypeScript Middleware uchun eng yaxshi amaliyotlar
- Middleware funksiyalarini kichik va maqsadga yoʻnaltirilgan holda saqlang. Har bir middleware funksiyasi bitta vazifaga ega boʻlishi kerak.
- Middleware funksiyalaringiz uchun tushunarli nomlardan foydalaning. Nom middleware nimani bajarishini aniq koʻrsatishi kerak.
- Xatolarni toʻgʻri boshqaring. Har doim xatolarni ushlang va ularni
next(error)yordamida xatolarni boshqarish middleware'iga uzating. - Tur xavfsizligini oshirish uchun maxsus soʻrov/javob turlaridan foydalaning.
RequestvaResponseinterfeyslarini kerakli maxsus xususiyatlar bilan kengaytiring. - Middleware'ni aniq opsiyalar bilan sozlash uchun middleware fabrikalaridan foydalaning.
- Middleware funksiyalaringizni hujjatlashtiring. Middleware nimani bajarishini va undan qanday foydalanish kerakligini tushuntiring.
- Middleware funksiyalaringizni sinchiklab tekshiring. Middleware funksiyalaringizning toʻgʻri ishlashini ta'minlash uchun birlik testlarini yozing.
Xulosa
TypeScript statik turlashni qoʻshish, kodning qulayligini oshirish va xatolarni dastlabki bosqichlarda aniqlash orqali Express middleware'ini ishlab chiqishni sezilarli darajada yaxshilaydi. Maxsus soʻrov/javob turlari, middleware fabrikalari, asinxron middleware, xatolarni boshqarish middleware'i va soʻrovlarni tasdiqlash middleware'i kabi ilgʻor tur naqshlarini oʻzlashtirish orqali siz kuchli, kengaytiriladigan va tur xavfsizligiga ega Express ilovalarini yaratishingiz mumkin. Middleware funksiyalaringizni kichik, maqsadga yoʻnaltirilgan va yaxshi hujjatlashtirilgan holda saqlash uchun eng yaxshi amaliyotlarga rioya qilishni unutmang.