Як створити власний API за допомогою Node.js, Express та MongoDB

У сучасному цифровому світі API (інтерфейси програмування додатків) є основою для веб-застосунків. Незалежно від того, чи створюєте ви односторінковий додаток, мобільний додаток чи інтегруєтесь з іншими сервісами, наявність надійного API є критично важливою. У цьому туторіалі ми розглянемо створення власного RESTful API за допомогою Node.js, Express та MongoDB — потужного набору інструментів для побудови масштабованих серверних рішень.

Як студент третього курсу з веб-розробки, я усвідомив, що створення власних API значно покращує розуміння серверної архітектури. Ця стаття поділиться моїм досвідом і надасть покрокову інструкцію для студентів, які хочуть створити свої власні API.

Перед початком

Перед тим, як почати, переконайтесь, що у вас є:
- Базові знання JavaScript.
- Встановлений Node.js на вашому комп'ютері.
- Редактор коду (наприклад, VS Code або Sublime Text).
- Встановлений MongoDB локально або доступ до MongoDB Atlas.
- Інструмент для тестування API, такий як Postman.

Налаштування проєкту

Спершу створимо новий проєкт і встановимо необхідні залежності:

Створюємо директорію для проєкту

mkdir custom-api
cd custom-api

Ініціалізуємо Node.js проект

npm init -y

Встановлюємо необхідні пакети

npm install express mongoose dotenv cors
npm install --save-dev nodemon

Ці пакети виконують такі функції:
- express — веб-фреймворк для Node.js.
- mongoose — інструмент для моделювання даних MongoDB.
- dotenv — завантажує змінні середовища з файлу .env.
- cors — дозволяє робити запити між різними доменами.
- nodemon — автоматично перезапускає сервер під час розробки.

Структура проєкту

Щоб підтримувати організовану структуру, ми створимо такі каталоги:

custom-api/
├── node_modules/
├── config/
│ └── db.js
├── controllers/
│ └── productController.js
├── models/
│ └── Product.js
├── routes/
│ └── productRoutes.js
├── .env
├── .gitignore
├── package.json
└── server.js

Створюємо відповідні директорії:

mkdir config controllers models routes

Підключення до MongoDB

Для підключення до MongoDB створимо файл .env в кореневій директорії:

PORT=5000
MONGO_URI=mongodb://localhost:27017/apidb

Далі налаштуємо підключення до бази даних у файлі config/db.js:

const mongoose = require('mongoose');

const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});

console.log(MongoDB підключено: ${conn.connection.host});
} catch (error) {
console.error(Помилка: ${error.message});
process.exit(1);
}
};
module.exports = connectDB;

Створення моделі даних

Тепер створимо просту модель для продуктів у файлі models/Product.js:

const mongoose = require('mongoose');

const productSchema = mongoose.Schema({
name: {
type: String,
required: [true, 'Будь ласка, додайте назву продукту'],
trim: true
},
description: {
type: String,
required: [true, 'Будь ласка, додайте опис']
},
price: {
type: Number,
required: [true, 'Будь ласка, додайте ціну'],
min: 0
},
category: {
type: String,
required: [true, 'Будь ласка, додайте категорію']
},
inStock: {
type: Boolean,
default: true
}
}, {
timestamps: true
});
module.exports = mongoose.model('Product', productSchema);

Створення контролерів

Контролери містять логіку для обробки запитів. Давайте створимо контролер продуктів у файлі controllers/productController.js:

const Product = require('../models/Product');

// Отримати всі продукти
const getProducts = async (req, res) => {
try {
const products = await Product.find();
res.status(200).json(products);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

// Отримати один продукт
const getProductById = async (req, res) => {
try {
const product = await Product.findById(req.params.id);

if (!product) {
return res.status(404).json({ message: 'Продукт не знайдений' });
}

res.status(200).json(product);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

// Створити новий продукт
const createProduct = async (req, res) => {
try {
const product = await Product.create(req.body);
res.status(201).json(product);
} catch (error) {
res.status(400).json({ message: error.message });
}
};

// Оновити продукт
const updateProduct = async (req, res) => {
try {
const product = await Product.findById(req.params.id);

if (!product) {
return res.status(404).json({ message: 'Продукт не знайдений' });
}

const updatedProduct = await Product.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, runValidators: true }
);

res.status(200).json(updatedProduct);
} catch (error) {
res.status(400).json({ message: error.message });
}
};

// Видалити продукт
const deleteProduct = async (req, res) => {
try {
const product = await Product.findById(req.params.id);

if (!product) {
return res.status(404).json({ message: 'Продукт не знайдений' });
}

await product.deleteOne();
res.status(200).json({ message: 'Продукт видалено' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};

module.exports = {
getProducts,
getProductById,
createProduct,
updateProduct,
deleteProduct
};

Налаштування маршрутів

Тепер налаштуємо маршрути в файлі routes/productRoutes.js:

const express = require('express');
const router = express.Router();
const {
getProducts,
getProductById,
createProduct,
updateProduct,
deleteProduct
} = require('../controllers/productController');

// GET /api/products
router.get('/', getProducts);

// GET /api/products/:id
router.get('/:id', getProductById);

// POST /api/products
router.post('/', createProduct);

// PUT /api/products/:id
router.put('/:id', updateProduct);

// DELETE /api/products/:id
router.delete('/:id', deleteProduct);

module.exports = router;

Створення сервера

Давайте налаштуємо сервер у файлі server.js:

const express = require('express');
const dotenv = require('dotenv');
const cors = require('cors');
const connectDB = require('./config/db');

// Завантажуємо змінні середовища
dotenv.config();

// Підключаємося до бази даних
connectDB();

// Ініціалізуємо express
const app = express();

// Middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// Маршрути
app.use('/api/products', require('./routes/productRoutes'));

// Корінний маршрут
app.get('/', (req, res) => {
res.send('API працює...');
});

// Запускаємо сервер
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(Сервер працює на порту ${PORT}));

Тестування API

Оновіть секцію скриптів у package.json:

"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
}

Тепер запустимо сервер:

npm run dev

Ви побачите повідомлення:

Сервер працює на порту 5000
MongoDB підключено: localhost

Тепер протестуємо API-ендпоінти за допомогою Postman:

  1. Створити продукт (POST):
  • URL: http://localhost:5000/api/products
  • Тіло (raw JSON):

{ "name": "Бездротові навушники", "description": "Безшумні бездротові навушники з акумулятором на 20 годин", "price": 149.99, "category": "Електроніка", "inStock": true }

2. Отримання всіх продуктів (GET):

  • URL: http://localhost:5000/api/products

3. Отримання конкретного продукту (GET):

  • URL: http://localhost:5000/api/products/[product_id]

4. Оновлення продукту (PUT):

  • URL: http://localhost:5000/api/products/[product_id]
  • Тіло (raw JSON):

{ "price": 129.99, "inStock": false }

5. Видалення продукту (DELETE):

  • URL: http://localhost:5000/api/products/[product_id]

Додавання валідації вводу

Щоб підвищити надійність нашого API, давайте додамо валідацію вхідних даних. Для цього встановимо express-validator:

npm install express-validator

Тепер оновимо наші маршрути:

const express = require('express');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const {
getProducts,
getProductById,
createProduct,
updateProduct,
deleteProduct
} = require('../controllers/productController');

// Middleware для валідації
const validateProduct = [
body('name').notEmpty().withMessage('Name is required'),
body('description').notEmpty().withMessage('Description is required'),
body('price').isNumeric().withMessage('Price must be a number').isFloat({ min: 0 }).withMessage('Price must be positive'),
body('category').notEmpty().withMessage('Category is required'),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
}
];

// Маршрути
router.get('/', getProducts);
router.get('/:id', getProductById);
router.post('/', validateProduct, createProduct);
router.put('/:id', updateProduct);
router.delete('/:id', deleteProduct);

module.exports = router;

Висновок

Вітаємо! Ви успішно створили RESTful API за допомогою Node.js, Express і MongoDB. Цей API відповідає кращим практикам, включаючи правильну структуру проєкту, налаштування середовища, підключення до бази даних, проектування RESTful маршрутів, розділення логіки контролерів і валідацію вводу.

Цей фундамент можна розширити для створення більш складних API з такими функціями, як аутентифікація за допомогою JWT, обмеження швидкості, розширене фільтрування і пагінація, завантаження файлів та логування помилок.

Як веб-розробники, створення власних API дає нам повний контроль над даними і відкриває можливості для створення складних застосунків. Сподіваюсь, цей урок допоможе вам на вашому шляху в веб-розробці!

Наступні кроки

Щоб вдосконалити цей API, розгляньте:
- Додавання аутентифікації користувачів
- Реалізацію функціональності розширеного пошуку
- Налаштування автоматизованого тестування
- Документування API за допомогою Swagger
- Розгортання на хмарній платформі, як Heroku або AWS

Щасливого кодування!

Перекладено з: How to Build a Custom API with Node.js, Express, and MongoDB