Создаём API при помощи Node.js и Express
Код на гитхабе https://github.com/tutsplus/code-your-first-api-with-nodejs-and-express-connect-a-database
1. Разбираемся с REST API
REST Representational State Transfer (* передача репрезентативного состояния) – абстрактная концепция
REST предполагает возможность передачи части данных по запросу
Например, у нас есть коллекция данных о птицах, но по запросу "зяблик" мы передаём данные только о зяблике, и не передаём данные о воробьях и синицах.
RESTful API – API, который работает согласно принципам REST.
API получает запрос и отправляет ответ - данные в формате JSON
Принципы REST
1. Унифицированный интерфейс - запрос отправляется при помощи URI
2. Клиент-Сервер: сервер и клиент выполняют различные задачи: сервер хранит данные и выполняет с ними манипуляции, а клиент отправляет запросы и отображает ответы.
3. Взаимодействия без запоминания состояния: вся информация о каждом запросе содержится в нем самом и не зависит от состояния сессии.
4. Возможность использования кэш-памяти: клиент и сервер могут кэшировать ресурсы.
HTTP (HyperText Transfer Protocol) – метод взаимодействия клиентов с серверами в Интернете.
HTTP открывает соединение TCP (Transmission Control Protocol – протокол управления передачей) к порту сервера (80 для http, 443 для https).
По этому соединению клиент отправляет запрос, а сервер отправляет ответы, которые содержат код ответа и тело.
Методы запроса
GET - получение данных. Когда открыли страницу, это метод GET
POST - отправка данных на сервер. Например, регистрация пользователя это метод POST
PUT - обновление данных, например, при изменении настроек
DELETE
Коды ответа
1xx: Information (* Информация о процессе передачи)
2xx: Success (* Информация об успешном принятии и обработке запроса клиента)
3xx: Redirection (* Перенаправление)
4xx: Client Error (* Информация об ошибках со стороны клиента)
5xx: Server Error (* Информация об ошибках со стороны сервера)
Примеры
200 OK – запрос был выполнен успешно
404 Not Found - запрашиваемый ресурс не существует
301 Moved Permanently - перенаправление
500 Internal Server Error - ошибка сервера
Что касается API RESTful, коды всех ответов должны находиться в диапазоне
2xx
.Запрос | Ответ |
---|---|
GET | 200 (OK) |
POST | 201 (Created) (* Создано) |
PUT | 200 (OK) |
DELETE | 200 (OK),202 (Accepted) (* Принято) 204 (No Content) (* Нет содержимого) |
curl -i https://www.google.com
отправляет запрос по методу GET
Ответ начинается с HTTP/2 200
Команда
curl -i https://google.com
тоже отправляет запрос по методу GET
Но теперь ответ начинается с HTTP/2 301 - вначале происходит перенаправление
Эндпойнт - функция API, которая запускается при обращении к серверу по определенному URL и может принимать и обрабатывать запросы по методу GET, POST, PUT или DELETE.
URL API
Общепринятые рекомендации
1. В URL должны использоваться существительные, а не глаголы
2. Cуществительные должны быть указаны во множественном числе
3. В URL не должно содержаться расширения файла
Инициализируем проект
npm init -y
Устанавливаем модули
body-parser – для разбора тела запросов;
express – для создания нашего сервера;
mysql: драйвер MySQL;
request – для выполнения запросов HTTP (необязателен) ;
npm
install
body-parser express mysql request
const http = require('http');
const port = 3001;
const server = http.createServer((request, response) => {
response.end('Hello, server!')
})
server.listen(port, (error) => {
if (error) return console.log(`Error: ${error}`);
console.log(`Server is listening on port ${port}`)
})
Запустим в терминале команду
curl -i http://localhost:3001
Ответ сервера
HTTP/1.1 200 OK
Date: Sat, 01 Aug 2020 19:50:02 GMT
Connection: keep-alive
Content-Length: 14
Hello, server!
Создаем сервер Express
Создадим новый файл, app.js
Пишем код
Запустим в терминале команду
curl -i http://localhost:3000HTTP/1.1 200 OK
Date: Sat, 01 Aug 2020 19:50:02 GMT
Connection: keep-alive
Content-Length: 14
Hello, server!
Создадим новый файл, app.js
Пишем код
const express = require('express');
const port = 3000;
const app = express();
app.get('/', (request, response) => {
response.send('Hello, Express!');
});
const server = app.listen(port, (error) => {
if (error) return console.log(`Error: ${error}`);
console.log(`Server listening on port ${server.address().port}`);
});
Запустим в терминале команду
Ответ сервера немного другой. Указано, что сервер работает на базе Express и что есть заголовок Content-Type
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 14
ETag: W/"e-gaHDsc0MZK+LfDiTM4ruVL4pUqI"
Date: Sat, 01 Aug 2020 19:56:54 GMT
Connection: keep-alive
Hello, Server!
Устанавливаем модуль
body-parser
Этот модуль нужен для удобного разбора тела запроса подробнее
Подключаем его
Подключаем его
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
И, чтобы вместо простого текста в качестве ответа отправлялся JSON-объект, заменим
app.get('/', (request, response) => {
response.send('Hello, Express!');
});
на
app.get('/', (request, response) => {
response.send({message: 'Hello, Express!'});
});
Всё вместе
const express = require('express');
const bodyParser = require('body-parser');
const port = 3000;
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
app.get('/', (request, response) => {
response.send({message: 'Hello, Express!'});
});
const server = app.listen(port, (error) => {
if (error) return console.log(error);
console.log(`Server listening on port ${server.address().port}`);
});
Запрос
curl -i http://localhost:3000
вернёт
Content-Type: application/json; charset=utf-8
curl -i http://localhost:3000
вернёт
Content-Type: application/json; charset=utf-8
Создадим новую папку под названием routes и файл под названием routes.js. Подключим его в app.js.
const routes = require('./routes/routes');
В routes.js пишем код
const router = app => {
app.get('/', (request, response) => {
response.send({
message: 'Node.js and Express REST API'
});
});
}
module.exports = router;
В app.js вместо app.get() вызываем routes(app)
Создадим переменную users в routes.js с некоторыми выдуманными пользовательскими данными в формате JSON
const users = [
{
id: 1,
name: "Richard Hendricks",
email: "richard@piedpiper.com",
},
{
id: 2,
name: "Bertram Gilfoyle",
email: "gilfoyle@piedpiper.com",
},
];
Добавим еще один маршрут для обработки запросов по адресу /users и методу GET в наш маршрутизатор и будем отправлять с его помощью пользовательские данные.
app.get("/users", (request, response) => {
response.send(users);
});
Подключаем базу данных
Скачиваем https://www.mamp.info/en/downloads/ и устанавливаем MAMP https://www.youtube.com/watch?v=gtZpq-p4OfA
Для просмотра базы данных скачиваем и устанавливаем SQLyog
Создаём новую базу данных
How to create Database and Table using SQLyog https://www.youtube.com/watch?v=y14p5rit35I
Скачиваем https://www.mamp.info/en/downloads/ и устанавливаем MAMP https://www.youtube.com/watch?v=gtZpq-p4OfA
Для просмотра базы данных скачиваем и устанавливаем SQLyog
Создаём новую базу данных
How to create Database and Table using SQLyog https://www.youtube.com/watch?v=y14p5rit35I
Добавляем таблицу с данными
Load MySQL Database using SQLyog https://www.youtube.com/watch?v=zNWEl5POp9A
Создаём папку data и в ней файл config.js.
Код
Подключаем config.js. в router.js.
Заменяем
на
По адресу http://localhost:3000/users открывается JSON файл с данными
Получить данные пользователя по его id
В файл router.js добавим ещё один эндпойнт
По ссылке http://localhost:3000/users/1 открываются данные первого пользователя, по ссылке http://localhost:3000/users/2 - второго
Добавление пользователя
Добавление данных происходит по методу POST
В файл router.js добавим эндпойнт
Пользователя добавим выполнив в терминале команду
curl -d "name=Dinesh Chugtai&email=dinesh@piedpiper.com" http://localhost:3000/users
Изменение данных существующего пользователя.
Для изменения данных существующего пользователя выполняем запрос по методу PUT
Запрос
Данные пользователя изменим выполнив в терминале команду
curl -X PUT -d "name=Bertram Gilfoyle" -d "email=bertram@piedpiper.com" http://localhost:3000/users/2
Удаление пользователя
curl -X DELETE http://localhost:3000/users/4
Отправка запросов при помощи модуля request
Запросы при помощи curl мы использовали только в тестовых целях
Создадим файл post.js
Код
Этот код добавляет ещё одного пользователя, если в терминале выполнить команду node post
Непонятно, правда, как добавить сразу много пользователей
Отправление запросов при помощи веб-формы
Обычно запросы отправляются при помощи HTML-форм
Создадим файл index.html
Открываем в браузере, заполняем поля, отправляем форму.
Данные добавились.
Код
const mysql = require('mysql');
const config = {
host: 'localhost',
user: 'root',
password: 'root',
database: 'api',
};
const pool = mysql.createPool(config);
module.exports = pool;
Подключаем config.js. в router.js.
const pool = require("../data/config");
Заменяем
app.get("/users", (request, response) => {
response.send(users);
});
на
app.get("/users", (request, response) => {
pool.query("SELECT * FROM users", (error, result) => {
if (error) throw error;
response.send(result);
});
});
По адресу http://localhost:3000/users открывается JSON файл с данными
Получить данные пользователя по его id
В файл router.js добавим ещё один эндпойнт
app.get("/users/:id", (request, response) => {
const id = request.params.id;
pool.query("SELECT * FROM users WHERE id = ?", id, (error, result) => {
if (error) throw error;
response.send(result);
});
});
По ссылке http://localhost:3000/users/1 открываются данные первого пользователя, по ссылке http://localhost:3000/users/2 - второго
Добавление пользователя
Добавление данных происходит по методу POST
В файл router.js добавим эндпойнт
app.post("/users", (request, response) => {
pool.query("INSERT INTO users SET ?", request.body, (error, result) => {
if (error) throw error;
response.status(201).send(`User added with ID: ${result.insertId}`);
});
});
Пользователя добавим выполнив в терминале команду
curl -d "name=Dinesh Chugtai&email=dinesh@piedpiper.com" http://localhost:3000/users
Изменение данных существующего пользователя.
Для изменения данных существующего пользователя выполняем запрос по методу PUT
Запрос
app.put('/users/:id', (request, response) => {
const id = request.params.id;
pool.query('UPDATE users SET ? WHERE id = ?', [request.body, id], (error, result) => {
if (error) throw error;
response.send('User updated successfully.');
});
Данные пользователя изменим выполнив в терминале команду
curl -X PUT -d "name=Bertram Gilfoyle" -d "email=bertram@piedpiper.com" http://localhost:3000/users/2
Удаление пользователя
app.delete('/users/:id', (request, response) => {
const id = request.params.id;
pool.query('DELETE FROM users WHERE id = ?', id, (error, result) => {
if (error) throw error;
response.send('User deleted.');
});
});
curl -X DELETE http://localhost:3000/users/4
Отправка запросов при помощи модуля request
Запросы при помощи curl мы использовали только в тестовых целях
Создадим файл post.js
Код
const request = require('request');
const json = {
"name": "Dinesh Chugtai",
"email": "dinesh@piedpiper.com",
};
request.post({
url: 'http://localhost:3000/users',
body: json,
json: true,
}, function (error, response, body) {
console.log(body);
});
Этот код добавляет ещё одного пользователя, если в терминале выполнить команду node post
Непонятно, правда, как добавить сразу много пользователей
Отправление запросов при помощи веб-формы
Обычно запросы отправляются при помощи HTML-форм
Создадим файл index.html
<body>
<form action="http://localhost:3000/users" method="post">
<label for="name">Name</label>
<input type="text" name="name">
<label for="email">Email</label>
<input type="email" name="email">
<input type="submit">
</form>
</body>
Открываем в браузере, заполняем поля, отправляем форму.
Данные добавились.