Магазин на JavaScript, часть 2 из 19. Обрабатываем HTTP запросы, добавляем маршруты
12.11.2021
Теги: Backend • Express.js • Frontend • JavaScript • Node.js • ORM • React.js • Web-разработка • БазаДанных • ИнтернетМагазин • КаталогТоваров • Корзина • Фреймворк
Обрабатываем GET-запрос
Сервер работает, но если мы попробуем открыть в браузере страницу localhost:7000
, то получим ошибку «Cannot GET /». Нужно указать серверу, какие endpoint обрабатывать и что делать при поступлении GET, POST, PUT и DELETE запросов. Так что открываем на редактирование файл index.js
— при GET-запросе на URL «/» — отправляем в ответ «Hello, world!».
/* .......... */ const app = express() app.get('/', (req, res) => { res.status(200).send('Hello, world!') }) const start = async () => { /* .......... */ } start()
Чтобы работать с данными в формате json — добавляем middleware:
/* .......... */ const app = express() app.use(express.json()) app.get('/', (req, res) => { res.status(200).json({message: 'Hello, world!'}) }) const start = async () => { /* .......... */ } start()
Когда мы создадим клиента, который будет работать с нашим сервером — то столкнемся с ошибкой «blocked by CORS policy». Допустим, наш клиент размещен на localhost:3000
, и на клиенте есть следующий код:
fetch('http://localhost:7000/') .then(response => response.text()) .then((result) => { document.body.textContent = result })
Браузеры не позволяют через javascript обращаться с одного домена (localhost:3000
) на другой (localhost:7000
) без разрешения со стороны запрашиваемого домена (то есть localhost:7000
). Чтобы разрешить клиентам с других доменов обращаться к нашему серверу, наш сервер должен отправить заголовки:
Access-Control-Allow-Origin: откуда можно отправлять запросы Access-Control-Allow-Methods: какие методы HTTP разрешены
Access-Control-Allow-Origin: * (разрешено с любого домена) Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD
Поэтому добавляем еще middleware, который эти заголовки отправит:
import config from 'dotenv/config' import express from 'express' import sequelize from './sequelize.js' import * as mapping from './models/mapping.js' import cors from 'cors' const PORT = process.env.PORT || 5000 const app = express() app.use(cors()) app.use(express.json()) app.get('/', (req, res) => { res.status(200).json({message: 'Hello, world!'}) }) const start = async () => { try { await sequelize.authenticate() await sequelize.sync() app.listen(PORT, () => console.log('Сервер запущен на порту', PORT)) } catch(e) { console.log(e) } } start()
Обрабатываем POST-запрос
Хорошо, теперь нам нужно расширение REST Client для VS Code для отправки POST-запроса — создаем файл test.http
(см. здесь):
GET / HTTP/1.1 Host: localhost:7000 ### POST / HTTP/1.1 Host: localhost:7000 Content-type: application/json; charset=utf-8 { "name": "Сергей", "age": 30 }
А наш сервер в ответ на POST-запрос будет возвращать тело запроса:
// обрабатываем GET-запрос app.get('/', (req, res) => { res.status(200).json({message: 'Hello, world!'}) }) // обрабатываем POST-запрос app.post('/', (req, res) => { res.status(200).json(req.body) })
Добавляем маршруты
Описывать все конечные точки в файле index.js
— плохая идея. Создадим для этой цели отдельную директорию routes
и внутри нее — файлы index.js
, product.js
, category.js
, brand.js
и user.js
.
import express from 'express' import product from './product.js' import category from './category.js' import brand from './brand.js' import user from './user.js' const router = new express.Router() router.use('/product', product) router.use('/category', category) router.use('/brand', brand) router.use('/user', user) export default router
import express from 'express' const router = new express.Router() router.get('/getall', (req, res) => res.status(200).send('Список всех товаров')) router.get('/getone/:id([0-9]+)', (req, res) => res.status(200).send('Получение одного товара')) router.post('/create', (req, res) => res.status(200).send('Создание нового товара')) router.put('/update/:id([0-9]+)', (req, res) => res.status(200).send('Обновление товара')) router.delete('/delete/:id([0-9]+)', (req, res) => res.status(200).send('Удаление товара')) export default router
import express from 'express' const router = new express.Router() router.get('/getall', (req, res) => res.status(200).send('Список всех категорий')) router.get('/getone/:id([0-9]+)', (req, res) => res.status(200).send('Получение одной категории')) router.post('/create', (req, res) => res.status(200).send('Создание новой категории')) router.put('/update/:id([0-9]+)', (req, res) => res.status(200).send('Обновление категории')) router.delete('/delete/:id([0-9]+)', (req, res) => res.status(200).send('Удаление категории')) export default router
import express from 'express' const router = new express.Router() router.get('/getall', (req, res) => res.status(200).send('Список всех брендов')) router.get('/getone/:id([0-9]+)', (req, res) => res.status(200).send('Получение одного бренда')) router.post('/create', (req, res) => res.status(200).send('Создание нового бренда')) router.put('/update/:id([0-9]+)', (req, res) => res.status(200).send('Обновление бренда')) router.delete('/delete/:id([0-9]+)', (req, res) => res.status(200).send('Удаление бренда')) export default router
import express from 'express' const router = new express.Router() router.post('/signup', (req, res) => res.status(200).send('Регистрация пользователя')) router.post('/login', (req, res) => res.status(200).send('Вход в личный кабинет')) router.get('/check', (req, res) => res.status(200).send('Проверка авторизации')) router.get('/getall', (req, res) => res.status(200).send('Список всех пользователй')) router.get('/getone/:id([0-9]+)', (req, res) => res.status(200).send('Получение одного пользователя')) router.post('/create', (req, res) => res.status(200).send('Создание нового пользователя')) router.put('/update/:id([0-9]+)', (req, res) => res.status(200).send('Обновление пользователя')) router.delete('/delete/:id([0-9]+)', (req, res) => res.status(200).send('Удаление пользователя')) export default router
Теперь сообщим приложению, какие маршруты у нас имеются — для этого редактируем index.js
:
import config from 'dotenv/config' import express from 'express' import sequelize from './sequelize.js' import * as mapping from './models/mapping.js' import cors from 'cors' import router from './routes/index.js' const PORT = process.env.PORT || 5000 const app = express() app.use(cors()) app.use(express.json()) app.use('/api', router) const start = async () => { try { await sequelize.authenticate() await sequelize.sync() app.listen(PORT, () => console.log('Сервер запущен на порту', PORT)) } catch(e) { console.log(e) } } start()
Для проверки, что все работает правильно — редактируем файл test.http
:
### Список всех товаров GET /api/product/getall HTTP/1.1 Host: localhost:7000 ### Получить один товар GET /api/product/getone/12345 HTTP/1.1 Host: localhost:7000 ### Создать новый товар POST /api/product/create HTTP/1.1 Host: localhost:7000 ### Обновить товар PUT /api/product/update/12345 HTTP/1.1 Host: localhost:7000 ### Удалить товар DELETE /api/product/delete/12345 HTTP/1.1 Host: localhost:7000
- Магазин на JavaScript, часть 19 из 19. Редактирование характеристик и рефакторинг приложения
- Магазин на JavaScript, часть 18 из 19. Панель управления: редактирование категорий и брендов
- Магазин на JavaScript, часть 17 из 19. Панель управления: список заказов, категорий и брендов
- Магазин на JavaScript, часть 15 из 19. Работа с заказами на сервере, оформление заказа
- Магазин на JavaScript, часть 14 из 19. Кнопка «Назад», страница товара, корзина покупателя
- Магазин на JavaScript, часть 13 из 19. Хранилище каталога, компонент витрины, кнопка «Назад»
- Магазин на JavaScript, часть12 из 19. Запросы на сервер, состояние приложения, Signup и Login
Поиск: Backend • Express.js • Frontend • JavaScript • Node.js • ORM • React.js • Web-разработка • База данных • Интернет магазин • Каталог товаров • Корзина • Фреймворк