initial commit

This commit is contained in:
2025-12-12 17:38:53 +03:00
commit 2bbc104000

463
README.md Normal file
View File

@@ -0,0 +1,463 @@
# Методические указания по разработке Web API на Node.js для школьников
## Введение
Данные методические указания предназначены для школьников, имеющих базовые навыки работы с HTML/CSS, Git и SSH. Цель курса — освоить основы разработки Web API с использованием Node.js и фреймворка Express за ограниченное время (3 часа на занятие и несколько занятий в семестр). Упор сделан на практические задания с минимально необходимой теорией.
---
## 📘 **Урок 1: Создание репозитория и организации структуры проекта**
### **Цель урока**: Создать GitHub-репозиторий, организовать структуру проекта и научиться работать с ветками в Git.
### **Краткая теория**:
- **GitHub** — платформа для хостинга и совместной разработки IT-проектов с использованием системы контроля версий Git.
- **Репозиторий** — хранилище кода и истории его изменений.
- **Ветка (branch)** — изолированная копия проекта для разработки новой функциональности без влияния на основной код (часто называется `main` или `master`).
### **Практические шаги**:
1. **Создайте репозиторий на GitHub**:
* Авторизуйтесь на [GitHub](https://github.com).
* Нажмите `+` в правом верхнем углу и выберите `New repository`.
* В поле `Repository name` укажите название, отражающее тему вашего API (например, `my-first-api`).
* Оставьте репозиторий публичным (`Public`).
* **Поставьте галочку** `Add a README.md`. Это создаст начальный файл описания проекта.
* Нажмите `Create repository`.
2. **Клонируйте репозиторий и создайте учебную ветку**:
```bash
# Склонируйте репозиторий на компьютер
git clone git@github.com:<ваш-логин>/<название-репозитория>.git
cd <название-репозитория>
# Создайте и переключитесь на новую ветку 'study'
git checkout -b study
# Если в команде двое, каждый создает свою ветку (например, study-ivanov)
# git checkout -b study-фамилия
```
### **Что должно получиться**:
* Создан удаленный репозиторий на GitHub с файлом `README.md`.
* На вашем компьютере есть локальная копия проекта.
* Вы находитесь в новой ветке (`study` или `study-фамилия`), а не в основной (`main`).
---
## 📦 **Урок 2: Инициализация проекта Node.js**
### **Цель урока**: Создать структуру папок для backend и инициализировать проект Node.js.
### **Краткая теория**:
- **Node.js** — это среда выполнения JavaScript вне браузера, которая позволяет создавать серверные приложения.
- **package.json** — это файл манифеста проекта Node.js, который содержит его описание, версию, список зависимостей и скриптов.
### **Практические шаги**:
1. **Создайте папку `backend`** и перейдите в неё:
```bash
mkdir backend
cd backend
```
2. **Инициализируйте проект Node.js**. Используйте флаг `-y`, чтобы принять значения по умолчанию, и `--type=module` для поддержки современного синтаксиса ES-модулей:
```bash
npm init -y --type=module
```
### **Проверка результата**:
Убедитесь, что в папке `backend` появился файл `package.json`. В его первой строке должно быть указано `"type": "module"`.
---
## 🚀 **Урок 3: Установка фреймворка Express**
### **Цель урока**: Установить библиотеку Express — популярный фреймворк для создания веб-приложений и API на Node.js.
### **Краткая теория**:
- **Express** — это минималистичный и гибкий фреймворк, который значительно упрощает создание серверных приложений и маршрутов.
- **Зависимости (dependencies)** — это сторонние библиотеки (пакеты), которые использует ваш проект. Они управляются с помощью `npm` (Node Package Manager).
### **Практические шаги**:
В папке `backend` выполните команду установки:
```bash
npm install express
```
### **Что должно получиться**:
* В файле `package.json` в раздел `"dependencies"` добавится `"express"` с номером версии.
* В проекте появится папка `node_modules`, где хранятся все установленные библиотеки.
---
## 🗑️ **Урок 4: Работа с `.gitignore` и первый коммит**
### **Цель урока**: Научиться игнорировать ненужные для репозитория файлы и зафиксировать изменения.
### **Краткая теория**:
- **`node_modules`** — это папка со всеми зависимостями проекта. Её **нельзя** добавлять в Git, так как она очень большая и её можно восстановить командой `npm install`.
- **`.gitignore`** — специальный файл, в котором перечисляются шаблоны файлов и папок, которые Git должен игнорировать.
### **Практические шаги**:
1. **Создайте файл `.gitignore`** в корне вашего проекта (на одном уровне с папкой `backend`).
2. **Добавьте в него шаблоны**. Вы можете создать базовое содержимое на сайте [gitignore.io](https://www.toptal.com/developers/gitignore). Введите `Node, Windows, VisualStudioCode` и скопируйте сгенерированный текст в ваш файл.
3. **Убедитесь, что в `.gitignore` есть строки**:
```
node_modules/
.env
```
4. **Выполните коммит**:
```bash
# Вернитесь в корень проекта (если вы в папке backend)
cd ..
# Добавьте все новые файлы в staging area
git add .
# Зафиксируйте изменения с комментарием
git commit -m "feat: инициализирован проект Node.js с Express, добавлен .gitignore"
```
---
## 📄 **Урок 5: Создание базовой структуры сервера**
### **Цель урока**: Создать основные файлы приложения и понять их роль.
### **Краткая теория**:
Серверное приложение на Express обычно разделяют на несколько файлов для лучшей организации:
- **`server.js`** — точка входа. Запускает сервер, подключает основные настройки.
- **`app.js`** — ядро приложения. Содержит настройки Express и все маршруты (routes).
### **Практические шаги**:
1. В папке `backend` создайте папку `src`.
2. Внутри `src` создайте два файла: `app.js` и `server.js`.
3. **В файл `app.js`** пока добавьте только создание экземпляра приложения:
```javascript
// backend/src/app.js
import express from 'express';
const app = express();
export default app; // Экспортируем app для использования в server.js
```
4. **В файл `server.js`** добавьте код запуска сервера:
```javascript
// backend/src/server.js
import app from './app.js';
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Сервер запущен и слушает порт ${PORT}`);
});
```
### **Что должно получиться**:
Создана модульная структура приложения. Пока при запуске сервер будет работать, но на любой запрос возвращать ошибку `404`, так как маршруты не определены.
---
## ▶️ **Урок 6: Первый запуск сервера**
### **Цель урока**: Запустить сервер и убедиться, что он работает, возвращая ожидаемую ошибку.
### **Практические шаги**:
1. Из папки `backend` выполните команду:
```bash
node src/server.js
```
2. В консоли должно появиться сообщение: `Сервер запущен и слушает порт 3000`.
3. Откройте браузер и перейдите по адресу `http://localhost:3000`.
4. **Вы должны увидеть стандартную страницу ошибки `Cannot GET /`**. Это ожидаемо, так как мы не создали обработчик для корневого маршрута (`/`).
5. Остановите сервер, нажав `Ctrl + C` в терминале.
6. **Выполните коммит**:
```bash
git add .
git commit -m "feat: создана базовая структура сервера, успешный запуск"
git push origin study # Или study-фамилия
```
---
## 🖐️ **Урок 7: Создание первого маршрута (Hello World)**
### **Цель урока**: Создать простейший обработчик GET-запроса и получить ответ от сервера.
### **Краткая теория**:
- **Маршрут (route)** — это правило, которое определяет, как сервер будет реагировать на клиентский запрос к определенному URL (конечной точке) и HTTP-методу (GET, POST и т.д.).
- **Обработчик (handler)** — функция, которая принимает запрос (`req`) и формирует ответ (`res`).
### **Практические шаги**:
1. Откройте файл `backend/src/app.js`.
2. **Добавьте обработчик для корневого маршрута (`/`) перед строкой `export default app;`**:
```javascript
// Обработчик GET-запроса на корневой URL '/'
app.get('/', (req, res) => {
// Устанавливаем заголовок ответа
res.setHeader('Content-Type', 'text/plain');
// Отправляем текстовый ответ
res.send('Hello World from my API!');
});
```
3. Запустите сервер снова (`node src/server.js`) и обновите страницу `http://localhost:3000` в браузере.
4. **Вы должны увидеть надпись `Hello World from my API!`**.
5. **Выполните коммит**.
---
## 🔢 **Урок 8: Работа с параметрами пути (Path Parameters)**
### **Цель урока**: Научиться создавать динамические маршруты и извлекать данные из URL.
### **Краткая теория**:
- **Статические маршруты** — это фиксированные адреса, например, `/about` или `/contacts`. Они всегда одинаковы.
- **Динамические маршруты** — это адреса, которые могут меняться. Например, страница профиля с разными именами пользователей: `/user/anna`, `/user/max`.
- **Параметры пути (Path Parameters)** — специальные части URL, которые меняются. В Express они обозначаются двоеточием (`:`), например: `/user/:username`.
- Когда кто-то заходит на `/user/anna`, Express видит `:username` в маршруте и понимает: "вместо `:username` подставлено `anna`". Это значение сохраняется в `req.params`.
### **Примеры разных параметров**:
1. **Один параметр**:
```javascript
// Когда заходят на /hello/Максим
app.get('/hello/:name', (req, res) => {
const name = req.params.name; // = "Максим"
res.send(`Привет, ${name}!`);
});
```
2. **Несколько параметров**:
```javascript
// Когда заходят на /book/сказки/5
app.get('/book/:genre/:page', (req, res) => {
const genre = req.params.genre; // = "сказки"
const page = req.params.page; // = "5"
res.send(`Жанр: ${genre}, Страница: ${page}`);
});
```
3. **Параметр в середине пути**:
```javascript
// Когда заходят на /category/электроника/product/123
app.get('/category/:categoryName/product/:productId', (req, res) => {
const category = req.params.categoryName; // = "электроника"
const productId = req.params.productId; // = "123"
res.send(`Категория: ${category}, Товар: ${productId}`);
});
```
### **Практические шаги**:
1. В файле `app.js` добавьте маршрут:
```javascript
// Пример запроса: GET http://localhost:3000/double/7
app.get('/double/:number', (req, res) => {
const input = req.params.number; // Получаем параметр из URL
// Проверяем, является ли параметр числом
if (!isNaN(input)) {
const number = parseFloat(input);
const result = number * 2;
res.send(`Если удвоить ${number}, получится ${result}`);
} else {
res.status(400).send('Пожалуйста, укажите число. Например: /double/10');
}
});
```
2. Протестируйте:
- `http://localhost:3000/double/7` → работает
- `http://localhost:3000/double/abc` → ошибка
---
## ➕➖✖️➗ **Урок 9: Практическое задание — Текстовый API-калькулятор**
### **Цель задания**: Создать простой калькулятор, который принимает числа в URL и возвращает текстовый результат.
### **Задание**:
Создайте 4 маршрута для основных математических операций. Формат ответа — обычный текст.
**Маршруты и примеры**:
1. **Сложение**: `GET /api/calc/sum/:a/:b`
- Пример: `GET /api/calc/sum/5/3`
- Ответ: `5 + 3 = 8`
2. **Вычитание**: `GET /api/calc/subtract/:a/:b`
- Пример: `GET /api/calc/subtract/10/4`
- Ответ: `10 - 4 = 6`
3. **Умножение**: `GET /api/calc/multiply/:a/:b`
- Пример: `GET /api/calc/multiply/7/2`
- Ответ: `7 * 2 = 14`
4. **Деление**: `GET /api/calc/divide/:a/:b`
- Пример: `GET /api/calc/divide/15/3`
- Ответ: `15 / 3 = 5`
### **Как это сделать**:
1. Для каждого маршрута получите параметры из `req.params.a` и `req.params.b`
2. Преобразуйте их в числа: `const num1 = parseFloat(req.params.a)`
3. Выполните операцию
4. Верните ответ в формате: ``res.send(`${num1} + ${num2} = ${result}`)``
### **Важно**:
- Пока не нужно проверять, корректные ли данные прислал пользователь
- Используйте шаблонные строки (обратные кавычки) для формирования ответа
---
## ⚠️ **Урок 10: Базовые проверки в калькуляторе**
### **Цель урока**: Добавить минимальную проверку входных данных.
### **Задание**:
Доработайте калькулятор из урока 9, добавив две простые проверки:
1. **Проверка, что оба параметра — числа**
2. **Для деления — проверка, что второй параметр не ноль**
### **Как это сделать**:
**Шаг 1: Проверка на число**
В начале каждого обработчика добавьте:
```javascript
const a = parseFloat(req.params.a);
const b = parseFloat(req.params.b);
// Проверяем, являются ли оба параметра числами
if (isNaN(a) || isNaN(b)) {
return res.status(400).send('Ошибка: оба параметра должны быть числами');
}
```
**Шаг 2: Проверка деления на ноль**
Только в обработчике деления добавьте после проверки на числа:
```javascript
// Проверка деления на ноль
if (b === 0) {
return res.status(400).send('Ошибка: на ноль делить нельзя');
}
```
### **Что должно происходить**:
- `/api/calc/sum/5/3` → `5 + 3 = 8` (работает)
- `/api/calc/sum/5/abc` → `Ошибка: оба параметра должны быть числами` (ошибка 400)
- `/api/calc/divide/10/0` → `Ошибка: на ноль делить нельзя` (ошибка 400)
---
## 📊 **Урок 11: Введение в формат JSON**
### **Цель урока**: Понять, что такое JSON и научиться отправлять данные в этом формате.
### **Краткая теория**:
- **JSON (JavaScript Object Notation)** — популярный формат для обмена данными;
- у JSON есть строгий набор правил:
- Все ключи в двойных кавычках
- Значения: строки (в кавычках), числа, true/false, null, массивы [], объекты {}
- **Пример JSON**:
```json
{
"имя": "Иван",
"возраст": 16,
"хобби": ["программирование", "шахматы"],
"студент": true
}
```
### **Практическое задание**:
1. Создайте маршрут `GET /api/user/:id`
2. Если `:id` — число, верните JSON с информацией о пользователе:
```javascript
app.get('/api/user/:id', (req, res) => {
const id = req.params.id;
if (!isNaN(id)) {
// Формируем вручную объект пользователя.
// Пока что просто притворимся, что мы загрузили его из базы данных.
const userData = {
userId: Number(id),
name: "Алексей Петров",
email: "alexey@example.com",
registered: true
};
// Отправляем как JSON
res.json(userData);
} else {
// Если id не число - ошибка в JSON формате
res.status(400).json({
error: "ID должен быть числом",
example: "/api/user/123"
});
}
});
```
3. Протестируйте в браузере:
- `http://localhost:3000/api/user/123` → увидите красиво оформленный JSON
- `http://localhost:3000/api/user/abc` → JSON с ошибкой
### Обратите внимание
В примере мы возвращаем фальшивые данные. С настоящими динамическими данными (списки/объекты БД) мы поработаем позже.
---
## 🔄 **Урок 12: Калькулятор с JSON-ответами**
### **Цель урока**: Переделать текстовый калькулятор для возврата JSON.
### **Задание**:
Измените все 4 операции калькулятора так, чтобы они возвращали данные в JSON-формате.
### **Формат успешного ответа**:
```json
{
"success": true,
"operation": "sum",
"arguments": {
"a": 5,
"b": 3
},
"result": 8
}
```
### **Формат ответа с ошибкой**:
```json
{
"success": false,
"error": {
"code": "DIVISION_BY_ZERO",
"message": "Делитель не может быть равен нулю"
}
}
```
### **Как изменить код**:
1. **Заменяем `res.send()` на `res.json()`**
2. **Для успешного ответа** формируем объект:
```javascript
const response = {
success: true,
operation: "sum", // или "subtract", "multiply", "divide"
arguments: {
a: a,
b: b
},
result: a + b // здесь ваша операция
};
res.json(response);
```
3. **Для ошибок**:
```javascript
res.status(400).json({
success: false,
error: {
code: "INVALID_NUMBERS", // или "DIVISION_BY_ZERO"
message: "Оба параметра должны быть числами"
}
});
```
### **Примеры кодов ошибок**:
- `"INVALID_NUMBERS"` — когда параметры не числа
- `"DIVISION_BY_ZERO"` — когда делим на ноль