1. Как Express работает с query-параметрами
Давайте вспомним, как выглядит обычная ссылка с параметрами:
https://example.com/search?query=express&limit=10
Здесь после знака вопроса ? идут пары "ключ=значение", разделённые амперсандом &. Эти параметры называются query-параметрами (или "строка запроса"). Они не входят в путь маршрута, а добавляют дополнительные данные к запросу.
Примеры использования query-параметров:
- Фильтрация и сортировка (например, /products?sort=price&order=asc)
- Пагинация (например, /articles?page=2&limit=20)
- Поиск (например, /search?q=express)
- Любые дополнительные опции, которые не влияют на сам маршрут
Как работает Express
Express автоматически разбирает строку запроса и кладёт все параметры в объект req.query. Это объект JavaScript, где ключи — имена параметров, а значения — строки (или массивы строк, если параметр повторяется).
Пример:
// URL: /search?query=express&limit=10
app.get('/search', (req, res) => {
console.log(req.query); // { query: 'express', limit: '10' }
});
Важно: Все значения в req.query — строки! Даже если вы передаёте число, оно будет строкой. Если параметр не был передан, его просто нет в объекте.
2. Синтаксис и базовые примеры
Пример 1: Получение одного параметра
app.get('/hello', (req, res) => {
// URL: /hello?name=Vasya
const name = req.query.name; // 'Vasya'
res.send(`Привет, ${name || 'гость'}!`);
});
Если параметр не передан, name будет undefined. В этом случае мы можем показать приветствие для "гостя".
Пример 2: Несколько параметров
app.get('/sum', (req, res) => {
// URL: /sum?a=3&b=5
const a = Number(req.query.a);
const b = Number(req.query.b);
if (isNaN(a) || isNaN(b)) {
return res.status(400).send('Некорректные параметры!');
}
res.send(`Сумма: ${a + b}`);
});
Здесь мы приводим значения к числам, потому что по умолчанию это строки.
Пример 3: Массивы в query-параметрах
Иногда параметры могут повторяться:
/tags?tag=js&tag=node&tag=express
Express превратит это в массив:
app.get('/tags', (req, res) => {
// req.query.tag будет либо строкой, либо массивом строк
const tags = req.query.tag;
res.send(`Теги: ${Array.isArray(tags) ? tags.join(', ') : tags}`);
});
Если параметр встречается один раз — это строка, если несколько — массив.
3. Практика: Фильтрация данных с помощью query-параметров
Давайте представим, что у нас есть массив пользователей. Мы хотим сделать маршрут /users, который может фильтровать пользователей по имени и возрасту через query-параметры.
Пример данных:
const users = [
{ id: 1, name: 'Alice', age: 23 },
{ id: 2, name: 'Bob', age: 31 },
{ id: 3, name: 'Charlie', age: 23 },
{ id: 4, name: 'Diana', age: 27 }
];
Реализация фильтрации:
app.get('/users', (req, res) => {
let result = users;
if (req.query.name) {
// Фильтруем по имени (без учёта регистра)
result = result.filter(
user => user.name.toLowerCase() === req.query.name.toLowerCase()
);
}
if (req.query.age) {
const age = Number(req.query.age);
if (!isNaN(age)) {
result = result.filter(user => user.age === age);
}
}
res.json(result);
});
Примеры запросов:
- /users — все пользователи
- /users?name=alice — только Alice
- /users?age=23 — Alice и Charlie
- /users?name=bob&age=31 — только Bob
4. Применяем query-параметры в нашем мини-приложении
В предыдущих лекциях мы начали строить простое API для работы со списком задач. Давайте расширим его, добавив фильтрацию по статусу задачи и поиск по названию через query-параметры.
Шаг 1: Данные
let tasks = [
{ id: 1, title: 'Почистить комнату', done: false },
{ id: 2, title: 'Купить хлеб', done: true },
{ id: 3, title: 'Позвонить маме', done: false }
];
Шаг 2: Маршрут со всеми задачами + фильтрация
app.get('/tasks', (req, res) => {
let result = tasks;
// Фильтрация по статусу (done)
if (req.query.done) {
// done=1 или done=true — значит показать только выполненные
const isDone = req.query.done === '1' || req.query.done === 'true';
result = result.filter(task => task.done === isDone);
}
// Поиск по названию (title)
if (req.query.title) {
const search = req.query.title.toLowerCase();
result = result.filter(task => task.title.toLowerCase().includes(search));
}
res.json(result);
});
Примеры запросов:
- /tasks — все задачи
- /tasks?done=1 — только выполненные
- /tasks?done=false — только невыполненные
- /tasks?title=хлеб — задачи, где в названии есть "хлеб"
- /tasks?done=0&title=позвонить — невыполненные задачи, где есть "позвонить"
5. Особенности и нюансы работы с req.query
Все значения — строки
Не забывайте, что любые параметры из req.query — это строки! Если вам нужны числа или булевы значения, приводите их явно. Например, Number(req.query.page), req.query.done === 'true'.
Параметр может отсутствовать
Если параметр не передан, его просто нет в объекте:
console.log(req.query.page); // undefined, если ?page=... не указан
Массивы
Если параметр повторяется в ссылке, Express делает из него массив:
/items?id=1&id=2&id=3
В req.query.id будет ['1', '2', '3'].
Пустые параметры
Если передать параметр без значения (?sort), Express считает его значением пустой строки ('').
Сравнение: req.query vs req.params
| req.query | req.params | |
|---|---|---|
| Где указывается | После ? в URL | В самом маршруте (/user/:id) |
| Как часто меняется | Можно добавлять любые параметры | Фиксированные в маршруте |
| Тип значений | Строки или массивы | Всегда строки |
| Пример | /search?name=Bob | /user/42 |
| Как получить | req.query.name | req.params.id |
6. Типичные ошибки при работе с req.query
Ошибка №1: Ожидание числа, а приходит строка
Очень частая ситуация: вы пишете if (req.query.page > 1), а забываете, что req.query.page — строка! В результате сравнение работает не так, как ожидается. Всегда приводите тип явно: Number(req.query.page).
Ошибка №2: Параметр не передан, а вы не проверяете на undefined
Если вы сразу используете req.query.sort.toLowerCase(), а пользователь не передал sort, получите ошибку "Cannot read property 'toLowerCase' of undefined". Всегда проверяйте:
if (req.query.sort) {
// ...
}
Ошибка №3: Путаете req.query и req.params
Иногда новички пытаются получить query-параметр через req.params, что не работает. Помните:
- /users/:id — это req.params.id
- /users?id=42 — это req.query.id
Ошибка №4: Не учитываете массивы
Если пользователь передал параметр несколько раз, Express отдаст массив. Если вы не ожидаете массив, а работаете только со строкой — возможны ошибки. Проверяйте тип:
const tags = req.query.tag;
if (Array.isArray(tags)) {
// обработать массив
} else if (tags) {
// обработать строку
}
Ошибка №5: Не экранируете пользовательский ввод
Если вы используете значения из query-параметров для поиска или фильтрации, всегда проверяйте и экранируйте их, чтобы избежать неожиданных ошибок и атак типа SQL-инъекций (если работаете с базой данных).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ