[Из песочницы] Создание REST API с Node.js и базой данных Oracle

Привет, Хабр! представляю вашему вниманию перевод статьи «Creating a REST API: Web Server Basics».

Часть 1. Создание REST API: основы веб-сервера


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

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

cd ~
mkdir hr_app
cd hr_app/
touch index.js
mkdir config
touch config/web-server.js
mkdir controllers
mkdir db_apis
mkdir services
touch services/web-server.js


Файл index.js можно рассматривать как «основной» файл в приложении. Он будет точкой входа в приложение. Мы будем добавлять код в этот файл и файлы web-server.js в каталогах config и services.

Вставьте следующий код в файл Home > hr_app > config>web-server.js

module.exports = {
  port: process.env.HTTP_PORT || 3000
};


В Node.js объект процесса имеет свойство env, которое содержит пользовательскую среду. Я использую это, чтобы установить значение порта в значение переменной среды HTTP_PORT. Если эта переменная среды не определена, значением по умолчанию будет 3000.
Вставьте следующий код в файл Home > hr_app > services>web-server.js

const http = require('http');
const express = require('express');
const webServerConfig = require('../config/web-server.js');
 
let httpServer;
 
function initialize() {
  return new Promise((resolve, reject) => {
    const app = express();
    httpServer = http.createServer(app);
 
    app.get('/', (req, res) => {
      res.end('Hello World!');
    });
 
    httpServer.listen(webServerConfig.port)
      .on('listening', () => {
        console.log(`Web server listening on localhost:${webServerConfig.port}`);
 
        resolve();
      })
      .on('error', err => {
        reject(err);
      });
  });
}
 
module.exports.initialize = initialize;


Строки 1–3: требуется несколько модулей. Модуль http включен в Node.js, но модуль Express необходимо будет установить через npm.

Строки 7–27: объявлена функция с именем initialize. Функция немедленно возвращает promise, которое разрешается или отклоняется в зависимости от того, успешно ли запущен веб-сервер.

Строки 9–10: создается новое экспресс-приложение (которое на самом деле является просто функцией), а затем используется для создания http-сервера через модуль http.

Строки 12–14: метод get приложения используется для добавления обработчика для запросов GET, которые приходят по корневому пути (/). Функция обратного будет вызываться при получении такого запроса, и она будет использовать параметр «res» (res) для отправки ответа «Hello World!» Клиенту.

Строки 16–24: метод прослушивания сервера используется для привязки к указанному порту и запуска прослушивания входящих запросов.

Строка 28: экспорт модуля чтоб можно было использовать извне

Вставьте следующий код в файл Home > hr_app > index.js

const webServer = require('./services/web-server.js');
 
async function startup() {
  console.log('Starting application');
 
  try {
    console.log('Initializing web server module');
 
    await webServer.initialize();
  } catch (err) {
    console.error(err);
 
    process.exit(1); // Non-zero failure code
  }
}
 
startup();


Подключаем модуль веб-сервера, а затем он определяет и вызывает асинхронную функцию startup. Поскольку функция initialize веб-сервера возвращает promise, вы можете использовать его с async / await и обернуть его в блок try-catch. Если функция initialize завершается успешно, веб-сервер будет работать; в противном случае любые исключения будут перехвачены и обработаны. Все, что вам нужно сделать сейчас, это инициализировать npm и установить Express — тогда вы можете запустить приложение. Выполните следующие команды в терминале из каталога hr_app.

npm init -y
npm install express -s
node .


Команда npm init используется для создания файла package.json, который npm использует как manifest файл (флаг -y принимает параметры по умолчанию). Команда npm install используется для установки express (флаг -s добавляет express в список зависимостей в package.json). Npm хранит установленные вами модули в каталоге node_modules. Он также создает файл с именем package.lock.json, чтобы обеспечить идентичное дерево для команды разработчиков.

Вы видите сообщение Web server listening on localhost:3000? Поздравляем, вы создали экспресс-сервер на базе!

И вот он, еще один «Hello World». Хотя это и не особенно увлекательно, это важный первый шаг для вашего API.

Когда будете готовы, можете выключить сервер, вернувшись к терминалу и нажав ctrl + c.

image

Контролируемый shutdown


Во время выключения нажатием Ctrl + C у вас нет контроля над тем, как это произошло. Чтобы контролировать процесс завершения работы, вам необходимо явно закрыть веб-сервер и выйти из процесса Node.js.

Вставьте следующий код в файл Home > hr_app >services>web-server.js

// *** previous code above this line ***
 
function close() {
  return new Promise((resolve, reject) => {
    httpServer.close((err) => {
      if (err) {
        reject(err);
        return;
      }
 
      resolve();
    });
  });
}
 
module.exports.close = close;


Функция close возвращает promise, который разрешается при успешном закрытии веб-сервера. Метод httpServer.close останавливает установление новых соединений, но не заставляет закрывать уже открытые соединения. В зависимости от того, сколько соединений открыто и что они делают, вам может потребоваться немного подождать, пока не сработает обратный вызов. Хотя вы не будете делать это в этом модуле, для принудительного закрытия открытых соединений можно использовать пользовательский код или модули npm, такие как http-shutdown.

Вставьте следующий код в файл Home > hr_app > index.js

// *** previous code above this line ***
 
async function shutdown(e) {
  let err = e;
    
  console.log('Shutting down');
 
  try {
    console.log('Closing web server module');
 
    await webServer.close();
  } catch (e) {
    console.log('Encountered error', e);
 
    err = err || e;
  }
 
  console.log('Exiting process');
 
  if (err) {
    process.exit(1); // Non-zero failure code
  } else {
    process.exit(0);
  }
}
 
process.on('SIGTERM', () => {
  console.log('Received SIGTERM');
 
  shutdown();
});
 
process.on('SIGINT', () => {
  console.log('Received SIGINT');
 
  shutdown();
});
 
process.on('uncaughtException', err => {
  console.log('Uncaught exception');
  console.error(err);
 
  shutdown(err);
});


События SIGINT и SIGTERM относятся к сигналам, которые могут быть отправлены процессу для его выключения, например, когда нажаты ctrl + c. Событие uncaughtException произойдет, когда ошибка JavaScript генерируется, но не перехватывается и обрабатывается с помощью оператора try-catch. Попробуйте запустить и снова закрыть приложение. Вы узнаете, что все работает правильно, когда увидите сообщения «выключения» в терминале.

Регистрация на сервере


Есть еще одна вещь, которая завершает наш модуль веб-сервера: HTTP logging. Существуют различные модули, которые вы можете использовать для этого типа логинига, но morgan Один из простых. Давайте установим morgan с помощью npm.

npm install morgan -s


Затем добавьте следующую строку в services / web-server.js под строкой, которая требует express (строка 2):

const morgan = require('morgan');


Теперь вы можете включить функцию morgan в качестве промежуточного программного обеспечения, через которую все запросы будут обрабатываться с помощью app.use. Добавьте эту строку перед вызовом app.get, который выдает сообщение «hello world».

// Combines logging info from request and response
    app.use(morgan('combined'));
 
    // *** app.get call below this line ***


Обратите внимание, что app.use создает конвейер (pipeline) функций промежуточного программного обеспечения (middleware), которые могут взаимодействовать с HTTP-запросами и ответами. Функции middleware будет выполняться в том порядке, в котором они включены. Перезапустите приложение и установите терминал так, чтобы вы могли видеть его и браузер одновременно. Каждый раз, когда вы перезагружаете страницу, вы должны видеть, что в терминале появляется новая запись в журнале. По умолчанию morgan передает информацию журнала в STDOUT (который отображается в терминале).

Следующая статья будет посвящена основам работы с базами данных, включая пулы соединений, которые помогут вам понять и построить API REST для Node.js.

© Habrahabr.ru