Создание REST API с Node.js и базой данных Oracle. Часть 3

Автор оригинала: Dan McGhan
  • Перевод

Часть 3. Создание REST API: обработка запросов GET


В предыдущей статье вы установили соединение с базой данных.

В этой же добавите логику маршрутизации, контроллера и базы данных для обработки HTTP-запроса GET на конечную точку API «employees».

Добавление логики маршрутизации


Express поставляется с классом Router, который упрощает маршрутизацию HTTP-запросов к соответствующей логике контроллера. Пути маршрутов определяют конечные точки URL API и могут содержать параметры маршрута, которые фиксируют значения в URL.

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

В этом приложении вы будете использовать немного более низкоуровневый подход, программно определяя маршруты через новый модуль маршрутизатора. Создайте новый файл с именем router.js в каталоге services. Добавьте следующий код в файл и сохраните изменения.

const express = require('express');
const router = new express.Router();
const employees = require('../controllers/employees.js');
 
router.route('/employees/:id?')
  .get(employees.get);
 
module.exports = router;

Модуль маршрутизатора начинается с того что запрашивается модуль Express, а затем создает новый экземпляр класса Router Express. Метод route модуля router используется для определения маршрута на основе переданных данных. Путь включает необязательный (из-за знака вопроса) параметр с именем id. Маршрут, возвращаемый из router, имеет методы, которые соответствуют методам HTTP и позволяют определять обработчики. В этом случае метод get используется для сопоставления входящего запроса GET с функцией get, определенной в контроллере сотрудников (которая будет создана ниже).

На данный момент у вас есть маршрутизатор, но он не используется в приложении. Чтобы использовать его, откройте файл services / web-server.js и удалите строку вверху, для которой требуется модуль базы данных (он использовался только для тестирования в предыдущем посте). Добавьте следующую строку кода на его место.

// *** line that requires ../config/web-server.js is here ***
const router = require('./router.js');

Затем используйте следующий код для замены всего обработчика app.get, который отвечает на запросы GET с использованием модуля базы данных (все 7 строк).

// *** line that adds morgan to app here ***
 
    // Mount the router at /api so all its routes start with /api
    app.use('/api', router);

Теперь router запрашивается в модуль веб-службы и «монтируется» в / api. Это означает, что полным URL-адресом для конечной точки сотрудников будет http: // server: port / api / employee /: id.

Добавление логики контроллера


Логика контроллера вступит в работу с момента, когда конечная точка URL и метод HTTP известны. Поскольку веб-сервер построен с использованием Express, логика контроллера будет определяться с помощью специального middleware или функций, которые имеют доступ к request и response объектам, а также к функции next.

Функция промежуточного программного обеспечения (middleware) будет использовать входные данные из объекта request для генерации ответа, который отправляется в response объект. Функция next обычно используется для вызова следующей функции промежуточного программного обеспечения в конвейере. Однако в этом API логика контроллера будет последним шагом в конвейере и завершит HTTP-ответ. Функция next будет вызываться только в случае возникновения ошибки, которая передает управление в стандартный обработчик ошибок Express.

Перейдите в каталог controllers и создайте новый файл с именем employee.js. Скопируйте и вставьте следующий код в файл и сохраните изменения.


/*01*/const employees = require('../db_apis/employees.js');
/*02*/ 
/*03*/async function get(req, res, next) {
/*04*/  try {
/*05*/    const context = {};
/*06*/ 
/*07*/    context.id = parseInt(req.params.id, 10);
/*08*/ 
/*09*/    const rows = await employees.find(context);
/*10*/ 
/*11*/    if (req.params.id) {
/*12*/      if (rows.length === 1) {
/*13*/        res.status(200).json(rows[0]);
/*14*/      } else {
/*15*/        res.status(404).end();
/*16*/      }
/*17*/    } else {
/*18*/      res.status(200).json(rows);
/*19*/    }
/*20*/  } catch (err) {
/*21*/    next(err);
/*22*/  }
/*23*/}
/*24*/
/*25*/module.exports.get = get;

Строка 1: API базы данных сотрудников (будет создана ниже).
Строки 3-23: объявлена асинхронная функция с именем get. Блок try-catch используется в теле функции для перехвата исключений, генерируемых в основном потоке, и передачи их следующей функции.
Строки 5-7: объявлена константа с именованным контекстом — это универсальный объект, который будет содержать свойства, относящиеся к методу поиска API базы данных. Свойство id добавляется в контекст на основе значения, которое приходит через req.params.id.
Строка 9: Метод find используется для извлечения соответствующих записей employees в базе данных.
Строки 11-19: условная логика используется для определения правильного кода состояния HTTP и тела ответа. Если один сотрудник был запрошен, но не найден, в качестве ответа отправляется код ошибки «404 Not Found». В противном случае отправляется код «200 OK» вместе с основанным на JSON телом ответа.
Строка 25: экспорт модуля чтоб можно добавить к другим модулям

Объект req.params — это всего лишь одно из нескольких свойств, используемых для получения данных из объекта входящего запроса. Другие общие свойства включают req.query для значений строки запроса в URL, req.body для тела запроса и req.cookies. Заголовки HTTP можно получить с помощью метода req.get.

Добавление логики базы данных


Чтобы запустить модуль базы данных сотрудников, перейдите в каталог db_apis и создайте новый файл с именем employee.js. Добавьте следующий код в файл.

const database = require('../services/database.js');
 
const baseQuery = 
 `select employee_id "id",
    first_name "first_name",
    last_name "last_name",
    email "email",
    phone_number "phone_number",
    hire_date "hire_date",
    job_id "job_id",
    salary "salary",
    commission_pct "commission_pct",
    manager_id "manager_id",
    department_id "department_id"
  from employees`;
 
async function find(context) {
  let query = baseQuery;
  const binds = {};
 
  if (context.id) {
    binds.employee_id = context.id;
 
    query += `\nwhere employee_id = :employee_id`;
  }
 
  const result = await database.simpleExecute(query, binds);
 
  return result.rows;
}
 
module.exports.find = find;

Модуль базы данных сотрудников вводит общий модуль базы данных и инициализирует константу с именем baseQuery для SQL-запроса в таблице сотрудников. Псевдонимы столбцов в двойных кавычках используются для управления регистром возвращаемых ключей.

Затем объявляется функция с именем find, которая используется для выполнения запроса и возврата извлеченных строк. Если переданный параметр context имеет значение «истинного» id, то к запросу добавляется предложение where, так что возвращается только один сотрудник.

Обратите внимание, что значение context.id не было добавлено к запросу напрямую. Вместо этого использовался местозаполнитель с именем: employee_id — это называется bind variable. Использование переменных связывания с базой данных Oracle очень важно с точки зрения безопасности и производительности. Значение bind variable присваивается объекту binds, который передается вместе с запросом в database.simpleExecute. Наконец, строки, полученные из базы данных, возвращаются вызывающей стороне.

Запустите приложение и перейдите в браузер по адресу http: // localhost: 3000 / api / employee. Вы должны увидеть список сотрудников следующим образом (я свернул пару):
image
Вы можете выбрать одного сотрудника, добавив идентификатор в конец URL-адреса, например: http: // localhost: 3000 / api / employee / 100.

image

На этом этапе ваш API может обрабатывать запросы GET на конечной точке сотрудников. В следующем посте вы расширите функциональность CRUD, добавив логику, которая обрабатывает запросы POST, PUT и DELETE.

Комментарии 0

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое