Каждая HTTP-сессия определяется двумя вещами:
- Запросом от клиента (браузера)
- Ответом от сервера
Во фреймворках запрос и ответ обычно представляются двумя объектами — request
и response
. В обработчик они приходят в качестве параметров, поэтому им можно задать любое имя. В примерах ниже их имена соответственно req
(request) и res
(response).
Response
Метод res.send()
формирует тело ответа:
app.get('/', (req, res) => {
res.send('Hello World!')
})
По умолчанию данные отдаются с заголовком Content-Type: text/plain. Даже если мы передадим в ответе HTML, тип контента все равно не поменяется, так как Fastify не анализирует что мы отдаем. Поэтому дополнительно придется менять тип:
app.get('/', (req, res) => {
res.type('text/html')
res.send('<h1>Hello Hexlet</h1>')
})
Если данные нужно отдать в виде JSON, то для этого указывать заголовок не обязательно. Фреймворк автоматически сформирует JSON и установит Content-Type равным json.
app.get('/', (req, res) => {
// res.type('text/html');
res.send({ userName: 'user1' })
})
Кроме тела ответа, мы можем установить заголовки и поменять код ответа.
app.get('/', (req, res) => {
res.header('key', 'value')
res.code(403)
res.send()
})
Еще мы можем выполнить редирект:
app.get('/admin', (req, res) => {
res.redirect(302, '/');
});
Request
Данные запроса можно получить с помощью свойств. Обычно такие вещи смотрят по необходимости, поэтому заучивать их смысла нет. Рассмотрим несколько самых базовых свойств:
app.get('/', (req, res) => {
req.body // Тело запроса
req.headers // Заголовоки
req.query // Все параметры запросов
req.query.name // Параметр запроса name
})
Параметры запроса
Параметры запроса не считаются частью маршрута и не влияют на выбор обработчика.
Это связано с тем, что они используются для разных вспомогательных целей — например, параметр page
обозначает страницу просматриваемого списка. В такой ситуации обработчик один и тот же, а вот данные — разные. Представим, что у нас есть вот такой код:
app.get('/users', (req, res) => {
// Отдаем обратно path + query params
res.send(req.originalUrl)
})
А теперь посмотрим, что он выводит в лог в ответ на разные запросы из браузера:
curl -X GET "http://localhost:3000/users"
/users
curl -X GET "http://localhost:3000/users?page=3"
/users?page=3
Во всех этих случаях фреймворк вызовет один и тот же обработчик, связанный с маршрутом /users. Фреймворк автоматически разбирает эти параметры и дает к ним удобный доступ через свойство объекта query
:
app.get('/users', (req, res) => {
const page = req.query.page
})
Параметры запроса не связаны с методом HTTP. Они могут приходить как на GET-запросы, так и на все остальные:
app.post('/users', (req, res) => {
const page = req.query.page
// ...
})
Тип параметров
С точки зрения HTTP, все переданные через него данные — это строки. Параметры не исключения — они так же являются строками:
const state = {
users: [
{
id: 1,
name: 'user',
},
],
}
app.get('/search', (req, res) => {
const { id } = req.query
const user = state.users.find(user => user.id === parseInt(id)) // Приведение к одному типу и сравнение
if (!user) {
res.code(404).send({ message: 'User not found' })
}
else {
res.send(user)
}
})
В примере выше в массиве state.users
хранятся данные о пользователе. Значение id
является числом. В обработчике параметр id
является строкой, поэтому при строгом сравнении происходит приведение к одному типу.
Самостоятельная работа
- Добавьте в проект hexlet-fastify обработчик, который будет обрабатывать GET запросы по адресу /hello и выводить приветствие. Обработчик должен использовать параметр запроса
name
и приветствовать пользователя по имени. Например, при запросеGET /hello?name=John
должно вывестись Hello, John!. Если параметр запросаname
не передан, должно вывестись Hello, World! - Запустите приложение и откройте страницу в браузере. Поэкспериментируйте с разными значениями параметра запроса
- Залейте изменения на GitHub
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.