В этой статье вы узнаете, как создать сервер API RESTful в Node.js с помощью Feathers.js .
Сервер API, также известный как сервер приложений , представляет собой программу, которая предоставляет данные для интерфейсных приложений. Он также обрабатывает бизнес-логику на стороне сервера и обеспечивает ограниченный доступ к базе данных организации. Это не только не позволяет посторонним лицам получить доступ к данным; он также может ограничивать вошедших в систему пользователей от доступа или изменения данных, если у них нет разрешения на это.
Каждое создаваемое вами приложение должно предоставлять услугу конечным пользователям. Для этого вашему приложению понадобятся данные для обработки. Вы можете использовать удаленные API для создания нового сервиса. Однако для большинства приложений вам необходимо управлять собственным хранилищем данных. Популярным вариантом является использование онлайн-сервисов хранения данных, таких как Firebase . Таким образом, вам не нужно разбираться с мельчайшими подробностями работы сервера распределенной базы данных. Однако для реализации вашего проекта может потребоваться использование полноценной внутренней системы управления базами данных, такой как MongoDB или Oracle. Чтобы ваше интерфейсное приложение получило доступ к данным, хранящимся в базе данных, вам потребуется серверное приложение, которое находится между базой данных и внешним приложением.
Как показано на диаграмме выше, работа сервера приложений заключается в получении доступа к данным из базы данных с помощью команд SQL или NoSQL и преобразовании в формат, понятный интерфейсным приложениям (клиентский браузер), например JSON. Кроме того, сервер приложений может использовать различные протоколы безопасности, такие как шифрование HTTPS и авторизация токенов, для обеспечения безопасности и надежности связи между базой данных и клиентским приложением. Одним из основных преимуществ использования такой архитектуры является то, что вы можете развертывать приложения, предназначенные для разных платформ — настольных, мобильных, веб-и т. Д. — с использованием одного сервера приложений. Кроме того, очень легко масштабировать ваше приложение по горизонтали, чтобы эффективно обслуживать большее количество пользователей с быстрым временем отклика.
Мы собираемся создать простой API-сервер и продемонстрировать различные функции, которые предоставляет Feathers.
Предпосылки
Прежде чем вы начнете следовать этому руководству, вы должны иметь хорошую основу в следующих темах:
Feathers построен на основе Express , минималистского веб-фреймворка для Node.js. Если вы завершили учебные пособия, показанные в ссылках, вы поймете, что создание RESTful API довольно утомительно, используя только Express. С Перьями большая часть повторяющейся работы уже сделана для вас. Вам нужно только сосредоточиться на настройке и настройке кода. Давайте углубимся в код и узнаем, как работает этот веб-фреймворк.
Создание проекта
Чтобы начать работу с Feathers, вам необходимо установить приложение командной строки глобально:
npm install -g @feathersjs/cli
Затем создайте новый проект API, используя команды ниже:
mkdir contacts-api cd contacts-api feathers generate app
Ниже приведены варианты, которые я выбрал. Не стесняйтесь выбирать любые рамки тестирования. К сожалению, тестирование выходит за рамки этой статьи, поэтому здесь оно не рассматривается. Лично мне нравится простота, и поэтому я пошел с Джестом .
После завершения установки вы можете открыть свой любимый редактор кода, чтобы посмотреть файлы проекта.
Если вы завершили обучение по Express, которое я перечислил в разделе предварительных требований, генерируемый код не должен вас пугать. Вот краткое резюме, которое описывает папки и файлы.
Не беспокойтесь о том, что каждый файл делает прямо сейчас. В этом уроке вы поймете, как они работают в курсе. А пока давайте подтвердим, что тесты работают.
пыление
Чтобы убедиться, что наш проект соответствует определенным правилам ESLint , просто запустите команду npm test
. Если вы работаете на платформе Unix или Linux, это должно работать нормально. Если вы работаете в Windows, вам нужно настроить несколько параметров, чтобы тесты выполнялись успешно.
Сначала зайдите в package.json
и посмотрите раздел скриптов. Измените test
строку на это:
"scripts": { "test": "npm run eslint && SET NODE_ENV= npm run jest", },
Далее, если вы установили Prettier в коде Visual Studio, вам нужно изменить значение одинарной кавычки на true
на вкладке настроек Workspace:
{ "prettier.singleQuote": true }
Наконец, убедитесь, что при создании или редактировании какого-либо файла конец строки имеет LF
. Если вы используете Visual Studio Code или аналогичный редактор, вы можете проверить текущий стиль окончания строки в строке состояния. Если написано CRLF
, измените на LF
. Внесение этих изменений поможет вам пройти тесты на волокно. К сожалению, чтобы пройти тесты, потребуется немного больше работы, которая не будет здесь рассмотрена.
Давайте посмотрим, как мы можем сгенерировать CRUD RESTful интерфейс.
Создать сервис
Создание интерфейса API Restful CRUD в Express требует небольшой работы. В Feathers все, что вам нужно сделать, это выполнить одну команду, ответить на несколько вопросов и сгенерировать для вас код:
$ feathers generate service ? What kind of service is it? NeDB ? What is the name of the service? contacts ? Which path should the service be registered on? /contacts ? What is the database connection string? nedb://../data force config\default.json create src\services\contacts\contacts.service.js force src\services\index.js create src\models\contacts.model.js create src\services\contacts\contacts.hooks.js create test\services\contacts.test.js
Мы будем использовать базу данных NeDB для этого урока. Feathers поддерживает обе базы данных SQL, такие как MySQL, и базы данных NoSQL, такие как MongoDB . Однако установка системы базы данных — на вашем компьютере или на облачном сервере — требует определенного времени для ее настройки. NeDB, с другой стороны, является базой данных в памяти, которая на 100% состоит из JavaScript и поддерживает подмножество API MongoDB. Там нет необходимости конфигурации; Вы просто устанавливаете это. Это отличная база данных для создания прототипов и тестирования новых приложений. Это то, что мы будем использовать в этом уроке.
Давайте кратко рассмотрим некоторые из файлов, которые были созданы с помощью этой команды:
-
services/contacts/contact.service.js
. Это служба Feathers, предоставляющая конечные точки API CRUD для/contacts
. Довольно маленький, не правда ли? Это потому, что Перья делает тяжелую работу для нас. Это спасает нас от написания стандартного кода CRUD. -
services/contacts/contact.hooks.js
. Здесь мы настраиваем поведение CRUD-логики. У нас есть разделbefore
, где мы можем проверить или изменить данные до того, как Feathers выполнит чтение или запись в базу данных. У нас также есть разделafter
, где мы можем проверить или изменить результаты из базы данных, прежде чем она будет отправлена клиентскому приложению. Мы можем делать такие вещи, как ограничение доступа, проверка данных, выполнение операций объединения и вычисление значений для дополнительных полей или столбцов. -
models/contacts.model.js
. Здесь мы определяем модель и присоединяем ее к таблице базы данных. Здесь мы также определяем схему, которая может использоваться для проверки полей при добавлении или обновлении новой записи. К сожалению, NeDB не поддерживает схемы. Тем не менее, я привел пример модели, которая подключена к MongoDB, которая поддерживает функцию схемы через адаптерmongoose
:
"use strict"; const mongoose = require("mongoose"); const Schema = mongoose.Schema; require("mongoose-type-email"); const contactsSchema = new Schema({ name: { first: { type: String, required: [true, "First Name is required"] }, last: { type: String, required: false } }, email: { type: mongoose.SchemaTypes.Email, required: [true, "Email is required"] }, phone: { type: String, required: [true, "Phone is required"], validate: { validator: function(v) { return /^\+(?:[0-9] ?){6,14}[0-9]$/.test(v); }, message: "{VALUE} is not a valid international phone number!" } }, createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now } }); const contactsModel = mongoose.model("contacts", contactsSchema); module.exports = contactsModel;
Несмотря на ограничения использования NeDB, это все еще отличная база данных для прототипирования. Большинство баз данных NoSQL позволяют вам отправлять данные, используя любую структуру, без предварительного определения схемы. Разумнее будет реализовать схему после того, как будут выполнены требования проекта. При наличии схемы Feathers выполнит для вас проверку полей с использованием определенных вами правил. Вам понадобится готовая к работе база данных, такая как MongoDB, чтобы иметь возможность определять схему. Обратите внимание, что конфигурация для базы данных разработки определена в config/default.json
:
"nedb": "../data"
Здесь предоставляются учетные данные базы данных. У нас также есть другой файл config/production.json
именем config/production.json
. Это конфигурация производственной базы данных, которая используется при развертывании приложения Feathers. При разработке важно использовать отдельную базу данных. В противном случае вы рискуете удалить или повредить бизнес-данные в производственной базе данных.
Теперь, когда у нас настроен CRUD-сервис для contacts
, пришло время его развернуть. Вы можете запустить сервер Feather, используя команду npm start
. Обратите внимание, что этот сервер не поддерживает горячую перезагрузку. Поэтому вам нужно будет перезапускать его каждый раз, когда вы вносите изменения в код. Чтобы взаимодействовать с нашим приложением Feathers, нам понадобится инструмент браузера API, такой как Postman или Insomnia . Я буду использовать Insomnia в этом уроке, но вы можете легко следовать за Postman или любым другим инструментом.
Создайте новый запрос GET (нажмите Ctrl + N ) и присвойте ему заголовок «Список контактов». В разделе URL введите http://localhost:3030/contacts
. Когда вы нажмете кнопку « Отправить» , у вас должно появиться следующее представление:
Ничего! Наша база данных в настоящее время пуста, поэтому нам нужно создать несколько новых контактов. Создайте новый запрос под названием « Create Contact
. Заполните остальные поля, как показано ниже:
В случае, если вы забыли изменить МЕТОД на POST в вышеуказанной форме, вы можете сделать это позже. Измените метод на POST и измените вкладку Body
на JSON. Скопируйте следующие данные на вкладку JSON:
{ "name": { "first": "Jack", "last": "Bauer" }, "email": "[email protected]", "phone": "+1234567" }
Когда вы нажмете кнопку «Отправить», вы получите следующий ответ. Обратите внимание, что _id
был создан для вашего нового контакта.
Вернитесь к List Contacts
и снова нажмите кнопку Отправить . Вы должны получить следующий результат:
{ "total": 1, "limit": 10, "skip": 0, "data": [ { "name": { "first": "Jack", "last": "Bauer" }, "email": "[email protected]", "phone": "+1234567", "_id": "ybnRxL6s2QEGhj4i" } ] }
Вернитесь к Create Contact
и опубликуйте пару новых записей:
{ "name": { "first": "Chloe", "last": "O'Brian" }, "email": "[email protected]", "phone": "+1987654" }
{ "name": { "first": "Renee", "last": "Walker" }, "email": "[email protected]", "phone": "+150505050" }
Давайте теперь выполним обновление. Для этого мы не будем использовать HTTP-метод UPDATE. Этот метод полностью перезапишет запись. Мы хотим просто перезаписать одно поле, а не всю запись. Для этого мы будем использовать PATCH. Создайте новый запрос, Update Contact
как показано ниже:
В поле URL введите http://localhost:3030/contacts/{_id}
. Замените {_id}
идентификатором первой записи. Поместите следующие данные на вкладку JSON:
{ "email": "[email protected]" }
Нажмите кнопку Отправить . Вы должны получить следующий результат:
Обратите внимание, как остальные поля остаются нетронутыми. Далее мы собираемся удалить запись. Это легко. Просто создайте новый запрос DELETE и назовите его Delete Contact
. В поле URL используйте формат http://localhost:3030/contacts/{_id}
. Как и раньше, замените {_id}
идентификатором записи, которую вы хотите удалить. Нажав Отправить, вы удалите эту запись для вас. Вы можете подтвердить, снова выполнив запрос List Contact
.
Мы только что убедились, что все операции CRUD работают нормально. В следующем разделе мы узнаем, как настроить аутентификацию.
Аутентификация
Прямо сейчас наша конечная точка API /contacts
не защищена. Если бы мы развернули наше приложение на облачном сервере, любой, у кого есть URL, может получить доступ к нашим записям и манипулировать ими. Чтобы ограничить доступ, нам нужно настроить аутентификацию. Мы будем использовать JSON Web Token для реализации аутентификации в нашем приложении API. Выполните следующую команду, чтобы настроить его:
feathers generate authentication
Как вы можете видеть ниже, Feathers поддерживает различные способы аутентификации пользователей. Самым простым в настройке является опция «Local Username + Password».
Выберите следующие варианты для остальных вопросов.
Вы можете просмотреть файлы, которые были сгенерированы командой, которую вы только что выполнили:
Следующим шагом является создание нового пользователя. Мы можем сделать это, используя Insomnia или любой другой инструмент браузера API. Создайте новый запрос и назовите его Create User
:
На вкладке JSON отправьте следующие данные:
{ "email": "[email protected]", "password": "secret" }
Вы должны получить аналогичный ответ, как показано ниже:
Теперь у нас есть пользователь. Давайте подтвердим это, создав новый запрос List Users
и отправив URL-адрес http://localhost:3030/users
. К сожалению, вы получите следующий ответ:
Нам нужно пройти проверку подлинности, чтобы получить доступ к этим данным. Поскольку мы не разработали интерфейсное приложение, которое мы могли бы использовать для входа в систему, мы продолжим использовать браузер API. Создайте новый запрос и назовите его «Get JWT Token». Заполните форму, как показано ниже:
Этот запрос использует метод POST. Возможно, вы можете переименовать запрос «Логин» для большей наглядности. На вкладке JSON скопируйте следующие данные:
{ "strategy": "local", "email": "[email protected]", "password": "secret" }
Вы должны получить следующий ответ после нажатия кнопки отправки:
Скопируйте код токена (без двойных кавычек). Перейдите на страницу запроса List Users
, выберите вкладку Auth
и выберите Bearer
. Вставьте этот токен-код в поле TOKEN
.
Когда вы нажмете кнопку « Отправить» , вы получите список пользователей. Обратите внимание, что наша система аутентификации не полностью безопасна. Любой /users
конечной точкой URL-адреса /users
может создать новую учетную запись и получить доступ к нашей системе. Чтобы предотвратить несанкционированное создание новых учетных записей, нам также необходимо ограничить эту конечную точку. Откройте файл services/users/users.hooks.js
и обновите следующий фрагмент кода:
module.exports = { before: { //... create: [ hashPassword(), authenticate('jwt') ], //...
Это гарантирует, что только аутентифицированные пользователи могут создавать новые учетные записи. Следующим шагом также является защита конечной точки /contacts
. Просто откройте файл services/contacts/contacts.hooks.js
и обновите соответствующим образом:
const { authenticate } = require('@feathersjs/authentication').hooks; module.exports = { before: { all: [authenticate('jwt')], //... },
Перезапустите сервер Feathers, чтобы изменения в коде вступили в силу. Если вы попытаетесь выполнить запрос « List Contacts
, вы получите следующий ответ:
{ "name": "NotAuthenticated", "message": "No auth token", "code": 401, "className": "not-authenticated", "data": {}, "errors": {} }
Чтобы пройти аутентификацию, вам нужно установить токен на Bearer
как вы делали раньше. После этого вы можете отправить запрос и получить список контактов. Обратите внимание: срок действия приобретенного ранее токена истекает через день. Ради эффективности лучше использовать переменные среды, чтобы было проще обновлять все параметры запроса API одновременно. При создании клиентского приложения этот токен необходимо хранить в local storage
. Не используйте куки. В противном случае ваше приложение будет подвержено атакам CSRF . Ознакомьтесь с документацией Feathers по безопасности, чтобы узнать больше о других рисках безопасности, о которых вам следует знать.
Теперь, когда вы настроили аутентификацию, любой новый сервис, который вы создадите после этого, даст вам возможность защитить вашу новую конечную точку. Давайте теперь посмотрим на последнюю тему этого урока в следующем разделе.
Крючки
Хуки — это функции промежуточного программного обеспечения, которые прикрепляются до , после или при ошибках метода обслуживания. Они обычно используются для обработки таких событий, как ведение журнала, ограничение доступа, защита полей, заполнение связанных объектов, отправка уведомлений и т. Д. Если вы посмотрите на services/users/users.hooks.js
, вы увидите несколько встроенных хуков Feathers. Мы собираемся создать наш собственный крючок. Сначала остановите сервер и удалите таблицу базы данных data/contacts.db
. Затем создайте новый хук, сгенерировав его с помощью этой команды:
feathers generate hooks
Используйте следующие опции, чтобы создать пользовательский обработчик process-contact
:
В этом хуке мы хотим вставить два новых поля непосредственно перед обработкой запроса на Create Contact
.
-
createdBy
: ссылка на в настоящее время вошел в систему пользователя по _id -
createdOn
: добавить дату создания
Откройте файл hooks/process-contact.js
и обновите файл следующим образом:
module.exports = function(options = {}) { return async context => { return context; }; };
module.exports = function(options = {}) { return async context => { // Get authenticated user const user = context.params.user; //Extract Submitted Data const { data } = context; // Add new Fields context.data = { ...data, // Preserve submitted data createdBy: user._id, createdOn: new Date() }; return context; }; };
Затем создайте еще один хук, populate-user
, который будет прикреплять объект user
к каждой записи contact
запросу. Следуйте инструкциям согласно приведенному ниже снимку экрана:
Откройте файл hooks/populate-user
и вставьте следующий код:
// eslint-disable-next-line no-unused-vars module.exports = function(options = {}) { return async context => { const { app, method, result, params } = context; // Ensure contacts is an array. If it's a single contact, wrap it into an array const contacts = method === "find" ? result.data : [result]; // Fetch user object from each contact's createdBy await Promise.all( contacts.map(async contact => { contact.user = await app .service("users") .get(contact.createdBy, params); }) ); return context; }; };
Прочитайте комментарии, чтобы понять, как это работает. Теперь вы можете запустить сервер. Снова создайте три контакта, используя запрос Create Contact
. Установите токен на предъявителя, если вы этого еще не сделали. В противном случае вы получите ошибку авторизации. Такой ответ вы должны получить при создании нового контакта:
Резюме
Я надеюсь, что вы узнали, как быстро создать свой собственный сервер API RESTful. Мы только коснулись основ, и вы должны пройти полное руководство, чтобы узнать больше возможностей, которые Feathers может предоставить, чтобы помочь вам реализовать расширенные функции с минимальными усилиями. Вы также должны посетить страницу Awesome Feathers , которая содержит сокровищницу ресурсов. Если вам нужен плагин, пример проекта или учебник, вы, вероятно, найдете ссылку там. Вы должны также проверить Перья-плюс CLI , который является Перьями на стероидах. Он добавляет новые функции в дополнение к тому, что уже предоставляет интерфейс командной строки Feathers, например создание кода для заполнения и поддержки GraphQL.
Если вы хотите продолжить продвижение проекта contacts-api
, я бы посоветовал вам создать новое интерфейсное приложение с использованием фреймворка по вашему выбору. Создайте экран входа и страницы CRUD для конечных точек /contacts
и /users
. Удачи в реализации задачи.