Архитектура RESTful стала стандартом де-факто для создания веб-API. Однако создание RESTful API не так просто, как просто предоставление множества конечных точек. Существует несколько рекомендаций, которым вы должны следовать, чтобы разработать масштабируемый, удобный в сопровождении и простой в использовании API RESTful. В этой статье мы рассмотрим некоторые ключевые рекомендации по разработке REST API, включая методы HTTP, URI ресурсов и форматы ответов, а также предоставим примеры кода в Node.js и Express, чтобы проиллюстрировать эти концепции.

Правильно используйте HTTP-методы

Одним из ключевых принципов архитектуры RESTful является использование методов HTTP для взаимодействия с ресурсами. Каждый метод HTTP имеет определенное значение и должен использоваться правильно, чтобы ваш API был интуитивно понятным и простым в использовании. Вот наиболее распространенные методы HTTP и способы их использования:

  • GET: извлекает ресурс с сервера. Запросы GET следует использовать, когда клиент хочет прочитать ресурс.
  • POST: создает новый ресурс на сервере. Запросы POST следует использовать, когда клиент хочет создать новый ресурс.
  • PUT: обновляет существующий ресурс на сервере. Запросы PUT следует использовать, когда клиент хочет обновить существующий ресурс.
  • УДАЛИТЬ: Удаляет ресурс с сервера. Запросы DELETE следует использовать, когда клиент хочет удалить ресурс.

Вот пример того, как использовать эти методы HTTP в приложении Node.js и Express:

const express = require('express'); 
const app = express();

// GET request 
app.get('/users/:id', (req, res) => { 
// retrieve user with ID from the database 
  const user = { id: req.params.id, name: 'John Doe' };
  res.send(user);
});

// POST request 
app.post('/users', (req, res) => { 
// create a new user in the database 
  const newUser = { name: req.body.name };
  res.send(newUser);
});

// PUT request
app.put('/users/:id', (req, res) => {
// update user with ID in the database
  const updatedUser = { id: req.params.id, name: req.body.name };
  res.send(updatedUser);
});

// DELETE request
app.delete('/users/:id', (req, res) => {
// delete user with ID from the database
  res.sendStatus(204);
});

Определить URI ресурсов

Еще одна важная рекомендация по разработке REST API — определение URI ресурсов, которые являются интуитивно понятными, согласованными и простыми для понимания. Каждый ресурс должен иметь уникальный URI, который идентифицирует его на сервере. URI должен быть разработан таким образом, чтобы клиентам было легко его понять и использовать. Вот несколько рекомендаций по определению URI ресурсов:

Используйте существительные вместо глаголов: URI ресурсов должны быть разработаны вокруг существительных, которые представляют ресурсы, а не действия, которые могут быть выполнены с ними.

Используйте существительные во множественном числе: URI ресурсов должны использовать существительные во множественном числе для представления наборов ресурсов, а не существительные в единственном числе.

Используйте подресурсы: URI ресурсов могут быть иерархическими, при этом подресурсы представляют связанные ресурсы. Например, пост в блоге может иметь комментарии в качестве подресурса.

Вот пример того, как определить URI ресурсов в приложении Node.js и Express:

const express = require(’express’);
const app = express();

// Users resource 
app.get(’/users/:id’, (req, res) => { 
// retrieve user with ID from the database 
  const user = { id: req.params.id, name: 'John Doe' };
  res.send
});

app.post(’/users’, (req, res) => {
// create a new user in the database
  const newUser = { name: req.body.name };
  res.send(newUser);
});

app.put(’/users/:id’, (req, res) => {
// update user with ID in the database
  const updatedUser = { id: req.params.id, name: req.body.name };
  res.send(updatedUser);
});

app.delete(’/users/:id’, (req, res) => {
// delete user with ID from the database
  res.sendStatus(204);
});

// Posts resource
app.get(’/posts/:id’, (req, res) => {
// retrieve post with ID from the database
  const post = { id: req.params.id, title: 'My First Blog Post' };
  res.send(post);
});

app.post(’/posts’, (req, res) => {
// create a new post in the database
  const newPost = { title: req.body.title, content: req.body.content };
  res.send(newPost);
});

app.put(’/posts/:id’, (req, res) => { 
// update post with ID in the database
  const updatedPost = { id: req.params.id, title: req.body.title, content: req.body.content };
  res.send(updatedPost);
});

app.delete(’/posts/:id’, (req, res) => {
// delete post with ID from the database
  res.sendStatus(204);
});

Используйте параметры запроса для фильтрации, сортировки и разбиения на страницы

Параметры запроса можно использовать для фильтрации, сортировки и разбивки на страницы результатов RESTful API. Параметры запроса — это дополнительные параметры, которые добавляются в конец URI и отделяются знаком вопроса (?). Вот несколько рекомендаций по использованию параметров запроса:

Используйте параметры запроса для фильтрации результатов. Параметры запроса можно использовать для фильтрации результатов на основе определенных критериев. Например, вы можете фильтровать пользователей по возрасту или местоположению.

Используйте параметры запроса для сортировки результатов. Параметры запроса можно использовать для сортировки результатов по возрастанию или убыванию на основе определенного поля.

Используйте параметры запроса для разбиения результатов на страницы. Параметры запроса можно использовать для разбиения результатов на страницы, указав количество результатов на странице и номер страницы.

Вот пример того, как использовать параметры запроса в приложении Node.js и Express:

const express = require(’express’);
const app = express();

// Users resource
app.get(’/users’, (req, res) => {
// retrieve users from the database
const users = [ 
  { id: 1, name: 'John Doe’, age: 30 },
  { id: 2, name: 'Jane Doe’, age: 25 },
  { id: 3, name: 'Bob Smith’, age: 35 }, ];

// filter users by age
if (req.query.age) { 
  users = users.filter(user => user.age === req.query.age);
}

// sort users by name
if (req.query.sort === 'name’) {
  users = users.sort((a, b) => a.name.localeCompare(b.name));
} 

// paginate users
const perPage = req.query.perPage || 10;
const page = req.query.page || 1;
const startIndex = (page - 1) * perPage;
const endIndex = startIndex + perPage;
const results = users.slice(startIndex, endIndex);
res.send(results); });

// Posts resource
app.get(’/posts’, (req, res) => {
// retrieve posts from the database
const posts = [
  { id: 1, title: 'My First Blog Post’, content: 'Lorem ipsum dolor sit amet' },
  { id: 2, title: 'My Second Blog Post’, content: 'Lorem ipsum dolor sit amet' },
  { id: 3, title: 'My Third Blog Post’, content: 'Lorem ipsum dolor sit amet' },
];

// filter posts by title
if (req.query.title) {
  posts = posts.filter(post => post.title.includes(req.query.title));
}

// sort posts by date
if (req.query.sort === 'date’) {
  posts = posts.sort((a, b) => new Date(b.date) - new Date(a.date));
}

// paginate posts
const perPage = req.query.perPage || 10;
const page = req.query.page || 1;
const startIndex = (page - 1) * perPage; const endIndex = startIndex + perPage;
const results = posts.slice(startIndex, endIndex);res.send(results); });

В этом примере конечная точка /users принимает параметры запроса для фильтрации, сортировки и разбиения на страницы. Если указан параметр запроса возраста, пользователи фильтруются по возрасту. Если в параметре запроса сортировки указано имя значения, пользователи сортируются по имени. Если указаны параметры запроса perPage и page, пользователи разбиваются на страницы.

Точно так же конечная точка /posts принимает параметры запроса для фильтрации, сортировки и разбиения на страницы. Если указан параметр запроса title, посты фильтруются по заголовку. Если в параметре запроса сортировки указана дата валютирования, сообщения сортируются по дате. Если указаны параметры запроса perPage и page, сообщения разбиваются на страницы.

Используйте коды состояния HTTP для передачи статуса API

Коды состояния HTTP используются для передачи статуса HTTP-запроса. Это трехзначные числа, которые указывают, был ли конкретный HTTP-запрос успешно выполнен, произошла ошибка или требуются дальнейшие действия. Вот некоторые распространенные коды состояния HTTP и их значения:

200 OK: запрос выполнен успешно.

201 Created: Запрос выполнен и создан новый ресурс.

204 No Content: запрос выполнен успешно, но тело ответа отсутствует.

400 Bad Request: запрос невозможно понять или в нем отсутствовали необходимые параметры.

401 Неавторизовано: учетные данные аутентификации недействительны или отсутствуют.

403 Запрещено: у пользователя нет разрешения на доступ к запрошенному ресурсу.

404 Not Found: Запрошенный ресурс не найден.

500 Внутренняя ошибка сервера: Произошла ошибка на сервере.

Вот пример того, как использовать коды состояния HTTP в приложении Node.js и Express:

const express = require('express');
const app = express();

// Users resource
app.get('/users/:id', (req, res) => {
// retrieve user with ID from the database
  const user = { id: req.params.id, name: 'John Doe' };
  if (user) {
    res.send(user);
  }
  else {
    res.status(404).send('User not found');
  }
});

app.post('/users', (req, res) => {
// create a new user in the database
  const newUser = { name: req.body.name };
  if (newUser) {
    res.status(201).send(newUser);
  }
  else {
    res.status(400).send('Bad request');
  }
});

app.put('/users/:id', (req, res) => {
// update user with ID in the database
  const updatedUser = { id: req.params.id, name: req.body.name };
  if (updatedUser) {
    res.send(updatedUser);
  }
  else {
    res.status(400).send('Bad request');
  }});

В этом примере конечная точка /users имеет три маршрута: GET /users/:id, POST /users и PUT /users/:id. Маршрут GET /users/:id извлекает пользователя с определенным идентификатором из базы данных. Если пользователь найден, вместе с данными пользователя возвращается код состояния 200 OK. Если пользователь не найден, возвращается код состояния 404 Not Found.

Маршрут POST /users создает нового пользователя в базе данных. Если новый пользователь успешно создан, вместе с данными пользователя возвращается код состояния 201 Created. Если возникает ошибка при создании нового пользователя, возвращается код состояния 400 Bad Request.

Маршрут PUT /users/:id обновляет пользователя с определенным идентификатором в базе данных. Если пользователь успешно обновлен, возвращается код состояния 200 OK вместе с обновленными данными пользователя. Если возникает ошибка при обновлении пользователя, возвращается код состояния 400 Bad Request.

Используйте аутентификацию и авторизацию для защиты вашего API

Аутентификация и авторизация — две важные концепции, когда речь идет о защите вашего API. Аутентификация — это процесс проверки личности пользователя или приложения, которое делает запрос к вашему API. Авторизация — это процесс предоставления или отказа в доступе к определенным ресурсам на основе разрешений аутентифицированного пользователя.

Существует несколько способов реализации аутентификации и авторизации в вашем API, в том числе:

  • Ключи API. Ключ API — это уникальный идентификатор, который используется для аутентификации запросов API. Ключи API часто используются для управления доступом к конечным точкам API и ограничения количества запросов, которые можно сделать.
  • OAuth 2.0: OAuth 2.0 — это структура авторизации, которая позволяет приложениям получать доступ к ресурсам от имени пользователя. С OAuth 2.0 пользователи могут предоставлять доступ к своим ресурсам, не сообщая свои учетные данные приложению.
  • Веб-токены JSON (JWT): JWT — это компактные, безопасные для URL-адресов средства представления требований, которые должны быть переданы между двумя сторонами. JWT можно использовать для аутентификации и авторизации запросов API.

Вот пример использования JWT для аутентификации и авторизации в приложениях Node.js и Express:

const express = require(’express’);
const jwt = require(’jsonwebtoken’);
const app = express();

// middleware to verify JWT token
function authenticateToken(req, res, next) {
  const authHeader = req.headers[’authorization’];
  const token = authHeader && authHeader.split(' ')[1];
  if (token == null)
    return res.sendStatus(401);
  
  jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
    if (err)
      return res.sendStatus(403);
    req.user = user;
    next();
  });
}

// login route
app.post(’/login’, (req, res) => {
// authenticate user
  const { username, password } = req.body;
  const user = { username: 'john', password: 'doe' };

  if (username === user.username && password === user.password) {
    const accessToken = jwt.sign(user, process.env.ACCESS_TOKEN_SECRET);
    res.json({ accessToken: accessToken});
  }
  else {
    res.send(’Invalid username or password’);
  }
});

// protected
route app.get(’/protected’, authenticateToken, (req, res) => { res.send(’Protected resource’); });

В этом примере маршрут /login принимает имя пользователя и пароль и возвращает JWT, если учетные данные действительны. JWT подписывается с использованием секрета, который хранится в переменной среды. Маршрут /protected — это защищенный ресурс, для доступа к которому требуется аутентификация. Промежуточное ПО authenticationToken используется для проверки токена JWT в заголовке запроса. Если токен действителен, промежуточное программное обеспечение устанавливает аутентифицированные пользовательские данные в объекте запроса, а «маршрут» отправляет «ответ» с данными защищенного ресурса.

Заключение

В этой статье мы рассмотрели основы REST API и обсудили пять основных тем, которые следует учитывать при создании API. Мы обсудили, как спроектировать API, выбрать правильные методы HTTP и коды состояния, обработать ошибки и исключения, внедрить маршрутизацию в Node.js и Express и защитить API с помощью аутентификации и авторизации.

Создание REST API требует тщательного планирования и внимания к деталям, но оно может быть мощным инструментом для создания веб-приложений и мобильных приложений. Следуя рекомендациям и рекомендациям, которые мы обсуждали в этой статье, вы можете обеспечить масштабируемость, эффективность и безопасность своего API.

Продолжая работать над своим API, обязательно помните об этих темах и будьте в курсе последних тенденций и технологий в разработке API. При правильном подходе вы можете создать API, который будет полезен вашим пользователям и поможет вашему бизнесу расти.