ExpressJS — Обзор
ExpressJS — это структура веб-приложений, которая предоставляет вам простой API для создания веб-сайтов, веб-приложений и серверных частей. С ExpressJS вам не нужно беспокоиться о протоколах низкого уровня, процессах и т. Д.
Что такое экспресс?
Express предоставляет минимальный интерфейс для создания наших приложений. Он предоставляет нам инструменты, необходимые для создания нашего приложения. Это гибкий инструмент , так как на npm доступно множество модулей, которые можно напрямую подключить к Express.
Express был разработан TJ Holowaychuk и поддерживается фондом Node.js и многочисленными участниками с открытым исходным кодом.
Зачем экспресс?
В отличие от своих конкурентов, таких как Rails и Django, которые имеют самоуверенный способ создания приложений, у Express нет «лучшего способа» что-либо сделать. Это очень гибкий и подключаемый.
мопс
Pug (ранее известный как Jade) — это краткий язык для написания HTML-шаблонов. Это —
- Производит HTML
- Поддерживает динамический код
- Поддерживает повторное использование (СУХОЙ)
Это один из самых популярных языков шаблонов, используемых в Express.
MongoDB и Mongoose
MongoDB — это база данных документов с открытым исходным кодом, разработанная для простоты разработки и масштабирования. Эта база данных также используется для хранения данных.
Mongoose — это клиентский API для node.js, который облегчает доступ к нашей базе данных из нашего приложения Express.
ExpressJS — Окружающая среда
В этой главе мы узнаем, как начать разработку и использование Express Framework. Для начала у вас должны быть установлены Node и npm (менеджер пакетов узлов). Если у вас их еще нет, перейдите к настройке узла для установки узла в вашей локальной системе. Убедитесь, что узел и npm установлены, выполнив следующие команды в вашем терминале.
node --version npm --version
Вы должны получить вывод, похожий на следующий.
v5.0.0 3.5.2
Теперь, когда у нас настроены Node и npm , давайте разберемся, что такое npm и как его использовать.
Диспетчер пакетов узлов (npm)
npm — менеджер пакетов для узла. Реестр npm — это общедоступная коллекция пакетов с открытым исходным кодом для Node.js, интерфейсных веб-приложений, мобильных приложений, роботов, маршрутизаторов и множества других потребностей сообщества JavaScript. npm позволяет нам получить доступ ко всем этим пакетам и установить их локально. Вы можете просмотреть список пакетов, доступных на npm на npmJS .
Как использовать npm?
Существует два способа установки пакета с использованием npm: глобально и локально.
-
Глобально — этот метод обычно используется для установки инструментов разработки и пакетов на основе CLI. Чтобы установить пакет глобально, используйте следующий код.
Глобально — этот метод обычно используется для установки инструментов разработки и пакетов на основе CLI. Чтобы установить пакет глобально, используйте следующий код.
npm install -g <package-name>
-
Локально — этот метод обычно используется для установки фреймворков и библиотек. Локально установленный пакет можно использовать только в том каталоге, в котором он установлен. Чтобы установить пакет локально, используйте ту же команду, что и выше, без флага -g .
Локально — этот метод обычно используется для установки фреймворков и библиотек. Локально установленный пакет можно использовать только в том каталоге, в котором он установлен. Чтобы установить пакет локально, используйте ту же команду, что и выше, без флага -g .
npm install <package-name>
Всякий раз, когда мы создаем проект с использованием npm, нам нужно предоставить файл package.json , в котором есть все подробности о нашем проекте. npm облегчает нам настройку этого файла. Давайте настроим наш проект развития.
Шаг 1 — Запустите свой терминал / cmd, создайте новую папку с именем hello-world и cd (создайте каталог) в нее —
Шаг 2 — Теперь, чтобы создать файл package.json с помощью npm, используйте следующий код.
npm init
Он попросит вас предоставить следующую информацию.
Просто продолжайте нажимать ввод и введите свое имя в поле «имя автора».
Шаг 3 — Теперь у нас есть настроенный файл package.json, далее мы установим Express. Чтобы установить Express и добавить его в наш файл package.json, используйте следующую команду —
npm install --save express
Чтобы убедиться, что Express установлен правильно, запустите следующий код.
ls node_modules #(dir node_modules for windows)
Совет — Флаг — save может быть заменен флагом -S . Этот флаг гарантирует, что Express будет добавлен в качестве зависимости к нашему файлу package.json . Это имеет преимущество: в следующий раз, когда нам понадобится установить все зависимости нашего проекта, мы можем просто запустить команду npm install, и она найдет зависимости в этом файле и установит их для нас.
Это все, что нам нужно, чтобы начать разработку с использованием платформы Express. Чтобы облегчить процесс разработки, мы установим инструмент из npm, nodemon. Этот инструмент перезапускает наш сервер, как только мы вносим изменения в любой из наших файлов, в противном случае нам необходимо перезапускать сервер вручную после каждой модификации файла. Чтобы установить nodemon, используйте следующую команду —
npm install -g nodemon
Теперь вы можете начать работать на Express.
ExpressJS — Hello World
Мы приступили к разработке, теперь пришло время приступить к разработке нашего первого приложения с использованием Express. Создайте новый файл с именем index.js и введите в него следующее.
var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send("Hello world!"); }); app.listen(3000);
Сохраните файл, перейдите в свой терминал и введите следующее.
nodemon index.js
Это запустит сервер. Чтобы протестировать это приложение, откройте браузер и перейдите по адресу http: // localhost: 3000, и отобразится сообщение, как на следующем снимке экрана.
Как работает приложение?
Первая строка импортирует Express в наш файл, у нас есть доступ к нему через переменную Express. Мы используем его для создания приложения и назначения его в var app.
app.get (маршрут, обратный вызов)
Эта функция сообщает, что делать, когда вызывается запрос get по заданному маршруту. Функция обратного вызова имеет 2 параметра: request (req) и response (res) . Объект запроса (req) представляет запрос HTTP и имеет свойства для строки запроса запроса, параметров, тела, заголовков HTTP и т. Д. Аналогично, объект ответа представляет ответ HTTP, который приложение Express отправляет, когда оно получает запрос HTTP.
res.send ()
Эта функция принимает объект в качестве входных данных и отправляет его запрашивающему клиенту. Здесь мы отправляем строку «Hello World!» ,
app.listen (порт, [хост], [отставание], [обратный вызов]])
Эта функция связывает и прослушивает соединения на указанном хосте и порте. Порт является единственным обязательным параметром здесь.
S.No. | Аргумент и описание |
---|---|
1 |
порт Номер порта, на который сервер должен принимать входящие запросы. |
2 |
хозяин Имя домена. Вы должны установить его при развертывании своих приложений в облаке. |
3 |
отставание Максимальное количество ожидающих соединений в очереди. По умолчанию это 511. |
4 |
Перезвоните Асинхронная функция, которая вызывается, когда сервер начинает прослушивать запросы. |
порт
Номер порта, на который сервер должен принимать входящие запросы.
хозяин
Имя домена. Вы должны установить его при развертывании своих приложений в облаке.
отставание
Максимальное количество ожидающих соединений в очереди. По умолчанию это 511.
Перезвоните
Асинхронная функция, которая вызывается, когда сервер начинает прослушивать запросы.
ExpressJS — Маршрутизация
Веб-фреймворки предоставляют ресурсы, такие как HTML-страницы, скрипты, изображения и т. Д. По разным маршрутам.
Следующая функция используется для определения маршрутов в приложении Express —
app.method (путь, обработчик)
Этот МЕТОД может быть применен к любому из HTTP-глаголов — получить, установить, положить, удалить. Также существует альтернативный метод, который выполняется независимо от типа запроса.
Путь — это маршрут, по которому будет выполняться запрос.
Обработчик — это функция обратного вызова, которая выполняется, когда на соответствующем маршруте найден соответствующий тип запроса. Например,
var express = require('express'); var app = express(); app.get('/hello', function(req, res){ res.send("Hello World!"); }); app.listen(3000);
Если мы запустим наше приложение и перейдем к localhost: 3000 / hello , сервер получит запрос get по маршруту «/ hello» , наше приложение Express выполнит функцию обратного вызова, прикрепленную к этому маршруту, и отправит «Hello World!» как ответ.
У нас также может быть несколько разных методов на одном и том же маршруте. Например,
var express = require('express'); var app = express(); app.get('/hello', function(req, res){ res.send("Hello World!"); }); app.post('/hello', function(req, res){ res.send("You just called the post method at '/hello'!\n"); }); app.listen(3000);
Чтобы проверить этот запрос, откройте свой терминал и используйте cURL для выполнения следующего запроса:
curl -X POST "http://localhost:3000/hello"
Express предоставляет специальный метод all для обработки всех типов методов http на определенном маршруте с использованием одной и той же функции. Чтобы использовать этот метод, попробуйте следующее.
app.all('/test', function(req, res){ res.send("HTTP method doesn't have any effect on this route!"); });
Этот метод обычно используется для определения промежуточного программного обеспечения, которое мы обсудим в главе о промежуточном программном обеспечении.
Маршрутизаторы
Определение маршрутов, как описано выше, очень утомительно. Чтобы отделить маршруты от нашего основного файла index.js , мы будем использовать Express.Router . Создайте новый файл things.js и введите в него следующее.
var express = require('express'); var router = express.Router(); router.get('/', function(req, res){ res.send('GET route on things.'); }); router.post('/', function(req, res){ res.send('POST route on things.'); }); //export this router to use in our index.js module.exports = router;
Теперь, чтобы использовать этот маршрутизатор в нашем index.js , введите следующее перед вызовом функции app.listen .
var express = require('Express'); var app = express(); var things = require('./things.js'); //both index.js and things.js should be in same directory app.use('/things', things); app.listen(3000);
Вызов функции app.use на маршруте «/ things» присоединяет маршрутизатор вещей к этому маршруту. Теперь любые запросы, которые наше приложение получает в «/ things», будут обрабатываться нашим маршрутизатором things.js. Маршрут «/» в things.js на самом деле является подчиненным маршрутом «/ things». Посетите localhost: 3000 / вещи /, и вы увидите следующий вывод.
Маршрутизаторы очень помогают в разделении проблем и хранят соответствующие части нашего кода вместе. Они помогают в создании поддерживаемого кода. Вы должны определить свои маршруты, относящиеся к объекту, в одном файле и включить его, используя вышеуказанный метод, в свой файл index.js .
ExpressJS — методы HTTP
Метод HTTP предоставляется в запросе и определяет операцию, запрошенную клиентом. В следующей таблице перечислены наиболее часто используемые методы HTTP.
S.No. | Метод и описание |
---|---|
1 |
ПОЛУЧИТЬ Метод GET запрашивает представление указанного ресурса. Запросы с использованием GET должны только извлекать данные и не должны иметь никакого другого эффекта. |
2 |
СООБЩЕНИЕ Метод POST запрашивает, чтобы сервер принял данные, включенные в запрос, в качестве нового объекта / объекта ресурса, идентифицированного URI. |
3 |
ПОЛОЖИЛ Метод PUT запрашивает, чтобы сервер принял данные, включенные в запрос, как модификацию существующего объекта, идентифицированного URI. Если он не существует, метод PUT должен его создать. |
4 |
УДАЛЯТЬ Метод DELETE запрашивает, чтобы сервер удалил указанный ресурс. |
ПОЛУЧИТЬ
Метод GET запрашивает представление указанного ресурса. Запросы с использованием GET должны только извлекать данные и не должны иметь никакого другого эффекта.
СООБЩЕНИЕ
Метод POST запрашивает, чтобы сервер принял данные, включенные в запрос, в качестве нового объекта / объекта ресурса, идентифицированного URI.
ПОЛОЖИЛ
Метод PUT запрашивает, чтобы сервер принял данные, включенные в запрос, как модификацию существующего объекта, идентифицированного URI. Если он не существует, метод PUT должен его создать.
УДАЛЯТЬ
Метод DELETE запрашивает, чтобы сервер удалил указанный ресурс.
Это самые распространенные методы HTTP. Чтобы узнать больше о методах, посетите http://www.tutorialspoint.com/http/http_methods.htm .
ExpressJS — Создание URL
Теперь мы можем определять маршруты, но они являются статическими или фиксированными. Чтобы использовать динамические маршруты, мы ДОЛЖНЫ предоставить различные типы маршрутов. Использование динамических маршрутов позволяет нам передавать параметры и обрабатывать их.
Вот пример динамического маршрута —
var express = require('express'); var app = express(); app.get('/:id', function(req, res){ res.send('The id you specified is ' + req.params.id); }); app.listen(3000);
Чтобы проверить это, перейдите на http: // localhost: 3000/123 . Следующий ответ будет отображаться.
Вы можете заменить «123» в URL-адресе на что-либо еще, и это изменение будет отражено в ответе. Более сложный пример вышесказанного —
var express = require('express'); var app = express(); app.get('/things/:name/:id', function(req, res) { res.send('id: ' + req.params.id + ' and name: ' + req.params.name); }); app.listen(3000);
Чтобы проверить приведенный выше код, перейдите по адресу http: // localhost: 3000 / things / tutorialspoint / 12345 .
Вы можете использовать объект req.params для доступа ко всем параметрам, которые вы передаете в URL. Обратите внимание, что выше 2 являются разными путями. Они никогда не будут пересекаться. Также, если вы хотите выполнить код, когда вы получаете «/ вещи», вам нужно определить его отдельно.
Маршруты, соответствующие шаблону
Вы также можете использовать регулярное выражение для ограничения соответствия параметров URL. Предположим, вам нужно, чтобы идентификатор представлял собой 5-значный длинный номер. Вы можете использовать следующее определение маршрута —
var express = require('express'); var app = express(); app.get('/things/:id([0-9]{5})', function(req, res){ res.send('id: ' + req.params.id); }); app.listen(3000);
Обратите внимание, что это будет соответствовать только запросам, которые имеют 5-значный длинный идентификатор . Вы можете использовать более сложные регулярные выражения для сопоставления / проверки ваших маршрутов. Если ни один из ваших маршрутов не соответствует запросу, вы получите сообщение «Cannot GET <your-request-route>» в качестве ответа. Это сообщение должно быть заменено страницей 404 не найден, используя этот простой маршрут —
var express = require('express'); var app = express(); //Other routes here app.get('*', function(req, res){ res.send('Sorry, this is an invalid URL.'); }); app.listen(3000);
Важно. Это следует указывать после всех ваших маршрутов, поскольку Express соответствует маршрутам от начала до конца файла index.js , включая необходимые вам внешние маршрутизаторы.
Например, если мы определяем те же маршруты, что и выше, при запросе с допустимым URL-адресом отображается следующий вывод. —
В случае неверного запроса URL-адреса отображается следующий вывод.
ExpressJS — Middleware
Функции промежуточного программного обеспечения — это функции, которые имеют доступ к объекту запроса (req) , объекту ответа (res) и следующей функции промежуточного программного обеспечения в цикле запроса-ответа приложения. Эти функции используются для изменения объектов req и res для таких задач, как разбор тел запросов, добавление заголовков ответов и т. Д.
Вот простой пример функции промежуточного программного обеспечения в действии:
var express = require('express'); var app = express(); //Simple request time logger app.use(function(req, res, next){ console.log("A new request received at " + Date.now()); //This function call is very important. It tells that more processing is //required for the current request and is in the next middleware function/route handler. next(); }); app.listen(3000);
Вышеуказанное промежуточное программное обеспечение вызывается для каждого запроса на сервере. Поэтому после каждого запроса мы получим следующее сообщение в консоли:
A new request received at 1467267512545
Чтобы ограничить его конкретным маршрутом (и всеми его подчиненными маршрутами), укажите этот маршрут в качестве первого аргумента app.use () . Например,
var express = require('express'); var app = express(); //Middleware function to log request protocol app.use('/things', function(req, res, next){ console.log("A request for things received at " + Date.now()); next(); }); // Route handler that sends the response app.get('/things', function(req, res){ res.send('Things'); }); app.listen(3000);
Теперь, когда вы запрашиваете какой-либо подчиненный маршрут «/ вещей», только тогда он будет записывать время.
Заказ звонков промежуточного программного обеспечения
Одна из самых важных вещей в промежуточном программном обеспечении в Express — это порядок, в котором они записаны / включены в ваш файл; порядок, в котором они выполняются, учитывая, что маршрут совпадает, также необходимо учитывать.
Например, в следующем фрагменте кода сначала выполняется первая функция, затем обработчик маршрута и затем функция завершения. В этом примере показано, как использовать промежуточное ПО до и после обработчика маршрута; также, как обработчик маршрута может использоваться в качестве промежуточного программного обеспечения.
var express = require('express'); var app = express(); //First middleware before response is sent app.use(function(req, res, next){ console.log("Start"); next(); }); //Route handler app.get('/', function(req, res, next){ res.send("Middle"); next(); }); app.use('/', function(req, res){ console.log('End'); }); app.listen(3000);
Когда мы запускаем «/» после запуска этого кода, мы получаем ответ как « Средний» и на нашей консоли —
Start End
Следующая диаграмма обобщает то, что мы узнали о промежуточном программном обеспечении —
Теперь, когда мы рассмотрели, как создать собственное промежуточное ПО, давайте обсудим некоторые из наиболее часто используемых промежуточных программ, созданных сообществом.
Стороннее промежуточное программное обеспечение
Список стороннего промежуточного программного обеспечения для Express доступен здесь . Ниже приведены некоторые из наиболее часто используемых промежуточного программного обеспечения; мы также узнаем, как их использовать / монтировать —
тело-анализатор
Это используется для анализа тела запросов, к которым прикреплены полезные данные. Чтобы смонтировать парсер тела, нам нужно установить его с помощью npm install —save body-parser и, чтобы смонтировать его, включите в ваш index.js следующие строки:
var bodyParser = require('body-parser'); //To parse URL encoded data app.use(bodyParser.urlencoded({ extended: false })) //To parse json data app.use(bodyParser.json())
Чтобы просмотреть все доступные опции для body-parser, посетите его страницу github.
печенье-анализатор
Он анализирует заголовок Cookie и заполняет req.cookies объектом, ключом которого являются имена файлов cookie. Чтобы смонтировать парсер cookie, нам нужно установить его с помощью npm install —save cookie-parser и, чтобы его смонтировать, включите в ваш index.js следующие строки:
var cookieParser = require('cookie-parser'); app.use(cookieParser())
экспресс-сессия
Создает промежуточное программное обеспечение сеанса с заданными параметрами. Мы обсудим его использование в разделе «Сессии».
У нас есть много других сторонних промежуточных программ в ExpressJS. Тем не менее, мы обсудили только несколько важных здесь.
ExpressJS — шаблоны
Мопс — движок шаблонов для Экспресса. Движки шаблонов используются для устранения загромождения кода нашего сервера с помощью HTML, дико объединяя строки с существующими шаблонами HTML. Pug — очень мощный движок шаблонов, который имеет множество функций, включая фильтры, включает в себя, наследование, интерполяцию и т. Д. Есть много оснований для этого.
Чтобы использовать Pug с Express, нам нужно установить его,
npm install --save pug
Теперь, когда Pug установлен, установите его как движок шаблонов для вашего приложения. Вам не нужно «требовать» этого. Добавьте следующий код в ваш файл index.js .
app.set('view engine', 'pug'); app.set('views','./views');
Теперь создайте новый каталог с именем views. Внутри этого создайте файл с именем first_view.pug и введите в него следующие данные.
doctype html html head title = "Hello Pug" body p.greetings#people Hello World!
Чтобы запустить эту страницу, добавьте следующий маршрут в ваше приложение —
app.get('/first_template', function(req, res){ res.render('first_view'); });
Вы получите вывод как — Hello World! Мопс преобразует эту очень простую на вид разметку в HTML. Нам не нужно отслеживать закрытие наших тегов, не нужно использовать ключевые слова class и id, лучше использовать ‘.’ и «#», чтобы определить их. Приведенный выше код сначала преобразуется в —
<!DOCTYPE html> <html> <head> <title>Hello Pug</title> </head> <body> <p class = "greetings" id = "people">Hello World!</p> </body> </html>
Мопс способен на гораздо большее, чем просто упрощение разметки HTML.
Важные особенности мопса
Давайте теперь рассмотрим несколько важных особенностей мопса.
Простые теги
Теги вложены в соответствии с их отступом. Как и в приведенном выше примере, тег <title> был вставлен в тег <head> , поэтому он был внутри него. Но тег <body> был на том же отступе, поэтому он был родным тегом <head> .
Нам не нужно закрывать теги, как только Pug встречает следующий тег на том же или внешнем уровне отступа, он закрывает тег для нас.
Чтобы поместить текст внутри тега, у нас есть 3 метода —
-
Пространство разделено
Пространство разделено
h1 Welcome to Pug
-
Трубопроводный текст
Трубопроводный текст
div | To insert multiline text, | You can use the pipe operator.
-
Блок текста
Блок текста
div. But that gets tedious if you have a lot of text. You can use "." at the end of tag to denote block of text. To put tags inside this block, simply enter tag in a new line and indent it accordingly.
Комментарии
Pug использует тот же синтаксис, что и JavaScript (//) для создания комментариев. Эти комментарии преобразуются в комментарии html (<! — comment ->). Например,
//This is a Pug comment
Этот комментарий преобразуется в следующее.
<!--This is a Pug comment-->
Атрибуты
Для определения атрибутов мы используем разделенный запятыми список атрибутов в скобках. Атрибуты класса и ID имеют специальные представления. Следующая строка кода описывает определение атрибутов, классов и идентификатора для данного HTML-тега.
div.container.column.main#division(width = "100", height = "100")
Эта строка кода преобразуется в следующую. —
<div class = "container column main" id = "division" width = "100" height = "100"></div>
Передача значений в шаблоны
Когда мы визуализируем шаблон Pug, мы можем фактически передать ему значение из нашего обработчика маршрута, который мы затем можем использовать в нашем шаблоне. Создайте новый обработчик маршрута со следующим.
var express = require('express'); var app = express(); app.get('/dynamic_view', function(req, res){ res.render('dynamic', { name: "TutorialsPoint", url:"http://www.tutorialspoint.com" }); }); app.listen(3000);
И создайте новый файл представления в каталоге представлений, названный dynamic.pug , со следующим кодом —
html head title=name body h1=name a(href = url) URL
Откройте localhost: 3000 / dynamic_view в вашем браузере; Вы должны получить следующий вывод —
Мы также можем использовать эти переданные переменные в тексте. Чтобы вставить переданные переменные в текст тега, мы используем синтаксис # {variableName} . Например, в приведенном выше примере, если мы хотим добавить приветствия из TutorialsPoint, мы могли бы сделать следующее.
html head title = name body h1 Greetings from #{name} a(href = url) URL
Этот метод использования значений называется интерполяцией . Приведенный выше код будет отображать следующий вывод. —
Conditionals
Мы также можем использовать условные операторы и циклические конструкции.
Рассмотрим следующее —
Если пользователь вошел в систему, на странице должно отображаться «Привет, пользователь», а если нет, то ссылка «Вход / Регистрация» . Чтобы достичь этого, мы можем определить простой шаблон как —
html head title Simple template body if(user) h1 Hi, #{user.name} else a(href = "/sign_up") Sign Up
Когда мы визуализируем это, используя наши маршруты, мы можем передать объект, как в следующей программе:
res.render('/dynamic',{ user: {name: "Ayush", age: "20"} });
Вы получите сообщение — Привет, Аюш . Но если мы не передадим объект или не передадим его без ключа пользователя, мы получим ссылку для регистрации.
Включить и компоненты
Мопс обеспечивает очень интуитивно понятный способ создания компонентов для веб-страницы. Например, если вы видите новостной сайт, заголовок с логотипом и категориями всегда фиксируется. Вместо того, чтобы копировать это в каждое создаваемое представление, мы можем использовать функцию включения . Следующий пример показывает, как мы можем использовать эту функцию —
Создайте 3 представления с помощью следующего кода —
HEADER.PUG
div.header. I'm the header for this website.
CONTENT.PUG
html head title Simple template body include ./header.pug h3 I'm the main content include ./footer.pug
FOOTER.PUG
div.footer. I'm the footer for this website.
Создайте маршрут для этого следующим образом —
var express = require('express'); var app = express(); app.get('/components', function(req, res){ res.render('content'); }); app.listen(3000);
Перейдите на localhost: 3000 / компоненты, вы получите следующий вывод —
include также может использоваться для включения открытого текста, CSS и JavaScript.
Есть много других особенностей мопса. Но это выходит за рамки этого урока. Вы можете дополнительно исследовать Мопса в Мопсе .
ExpressJS — Обслуживание статических файлов
Статические файлы — это файлы, которые клиенты загружают с сервера. Создать новый каталог, общедоступный . Express, по умолчанию не позволяет обслуживать статические файлы. Вам необходимо включить его с помощью следующего встроенного промежуточного программного обеспечения.
app.use(express.static('public'));
Примечание. Express ищет файлы относительно статического каталога, поэтому имя статического каталога не является частью URL-адреса.
Обратите внимание, что корневой маршрут теперь установлен на ваш публичный каталог, поэтому все загружаемые вами статические файлы будут считаться публичными как корневые. Чтобы проверить, что это работает нормально, добавьте любой файл изображения в ваш новый общедоступный каталог и измените его имя на « testimage.jpg ». В ваших представлениях создайте новое представление и включите этот файл как —
html head body h3 Testing static file serving: img(src = "/testimage.jpg", alt = "Testing Image
Вы должны получить следующий вывод —
Несколько статических каталогов
Мы также можем установить несколько каталогов статических ресурсов, используя следующую программу:
var express = require('express'); var app = express(); app.use(express.static('public')); app.use(express.static('images')); app.listen(3000);
Префикс виртуального пути
Мы также можем предоставить префикс пути для обслуживания статических файлов. Например, если вы хотите предоставить префикс пути, такой как «/ static» , вам нужно включить следующий код в ваш файл index.js:
var express = require('express'); var app = express(); app.use('/static', express.static('public')); app.listen(3000);
Теперь, когда вам нужно включить файл, например, файл скрипта с именем main.js, находящийся в вашем публичном каталоге, используйте следующий тег скрипта —
<script src = "/static/main.js" />
Этот метод может пригодиться при предоставлении нескольких каталогов в виде статических файлов. Эти префиксы могут помочь различать несколько каталогов.
ExpressJS — данные формы
Формы являются неотъемлемой частью Интернета. Почти каждый веб-сайт, который мы посещаем, предлагает нам формы, которые отправляют или получают некоторую информацию для нас. Чтобы начать работу с формами, мы сначала установим body-parser (для анализа JSON и URL-кодированных данных) и multer (для анализа multipart / form data) промежуточное программное обеспечение.
Чтобы установить body-parser и multer , перейдите в свой терминал и используйте —
npm install --save body-parser multer
Замените содержимое файла index.js следующим кодом —
var express = require('express'); var bodyParser = require('body-parser'); var multer = require('multer'); var upload = multer(); var app = express(); app.get('/', function(req, res){ res.render('form'); }); app.set('view engine', 'pug'); app.set('views', './views'); // for parsing application/json app.use(bodyParser.json()); // for parsing application/xwww- app.use(bodyParser.urlencoded({ extended: true })); //form-urlencoded // for parsing multipart/form-data app.use(upload.array()); app.use(express.static('public')); app.post('/', function(req, res){ console.log(req.body); res.send("recieved your request!"); }); app.listen(3000);
После импорта анализатора тела и multer мы будем использовать body-parser для синтаксического анализа запросов заголовков json и x-www-form-urlencoded, в то время как мы будем использовать multer для анализа multipart / form-data.
Давайте создадим HTML-форму, чтобы проверить это. Создайте новый вид с именем form.pug со следующим кодом —
html html head title Form Tester body form(action = "/", method = "POST") div label(for = "say") Say: input(name = "say" value = "Hi") br div label(for = "to") To: input(name = "to" value = "Express forms") br button(type = "submit") Send my greetings
Запустите ваш сервер, используя следующее.
nodemon index.js
Теперь перейдите на localhost: 3000 / и заполните форму, как вам нравится, и отправьте ее. Следующий ответ будет отображаться —
Посмотрите на вашу консоль; он покажет тело вашего запроса в виде объекта JavaScript, как на следующем снимке экрана —
Объект req.body содержит ваше проанализированное тело запроса. Чтобы использовать поля из этого объекта, просто используйте их как обычные объекты JS.
Это наиболее рекомендуемый способ отправки запроса. Есть много других способов, но они не имеют отношения к этому, потому что наше приложение Express будет обрабатывать все эти запросы одинаково. Чтобы узнать больше о различных способах подачи запроса, загляните на эту страницу.
ExpressJS — База данных
Мы продолжаем получать запросы, но в итоге нигде не храним их. Нам нужна база данных для хранения данных. Для этого мы будем использовать базу данных NoSQL под названием MongoDB .
Чтобы установить и прочитать о Mongo, перейдите по этой ссылке.
Чтобы использовать Mongo с Express, нам нужен клиентский API для узла. У нас есть несколько вариантов, но в этом уроке мы остановимся на мангусте . Mongoose используется для моделирования документов в Node для MongoDB. Для моделирования документов мы создаем модель (очень похожую на класс в документно-ориентированном программировании), а затем мы создаем документы, используя эту модель (как мы создаем документы класса в ООП). Вся наша обработка будет производиться на этих «документах», затем, наконец, мы запишем эти документы в нашу базу данных.
Настройка мангуста
Теперь, когда вы установили Mongo, давайте установим Mongoose точно так же, как мы устанавливали другие наши пакеты узлов —
npm install --save mongoose
Прежде чем мы начнем использовать mongoose, мы должны создать базу данных, используя оболочку Mongo. Чтобы создать новую базу данных, откройте свой терминал и введите «Монго». Запустится оболочка Mongo, введите следующий код —
use my_db
Новая база данных будет создана для вас. Всякий раз, когда вы открываете оболочку mongo, она по умолчанию будет «тестировать» БД, и вам придется перейти в базу данных, используя ту же команду, что и выше.
Чтобы использовать Mongoose, нам потребуется это в нашем файле index.js, а затем подключиться к сервису mongodb, работающему на mongodb: // localhost .
var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my_db');
Теперь наше приложение подключено к нашей базе данных, давайте создадим новую модель. Эта модель будет выступать в качестве коллекции в нашей базе данных. Чтобы создать новую модель, используйте следующий код перед определением любого маршрута —
var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model("Person", personSchema);
Приведенный выше код определяет схему для человека и используется для создания человека в режиме Mongoose.
Сохранение документов
Теперь мы создадим новую HTML-форму; эта форма поможет вам получить информацию о человеке и сохранить его в нашей базе данных. Чтобы создать форму, создайте новый файл представления с именем person.pug в каталоге представлений следующего содержания:
html head title Person body form(action = "/person", method = "POST") div label(for = "name") Name: input(name = "name") br div label(for = "age") Age: input(name = "age") br div label(for = "nationality") Nationality: input(name = "nationality") br button(type = "submit") Create new person
Также добавьте новый маршрут get в index.js для рендеринга этого документа —
app.get('/person', function(req, res){ res.render('person'); });
Перейдите к « localhost: 3000 / person », чтобы проверить правильность вывода формы. Обратите внимание, что это просто пользовательский интерфейс, он еще не работает. На следующем снимке экрана показано, как отображается форма.
Теперь мы определим обработчик почтового маршрута в / person, который будет обрабатывать этот запрос
app.post('/person', function(req, res){ var personInfo = req.body; //Get the parsed information if(!personInfo.name || !personInfo.age || !personInfo.nationality){ res.render('show_message', { message: "Sorry, you provided worng info", type: "error"}); } else { var newPerson = new Person({ name: personInfo.name, age: personInfo.age, nationality: personInfo.nationality }); newPerson.save(function(err, Person){ if(err) res.render('show_message', {message: "Database error", type: "error"}); else res.render('show_message', { message: "New person added", type: "success", person: personInfo}); }); } });
В приведенном выше коде, если мы получим любое пустое поле или не получим никакого поля, мы отправим ответ об ошибке. Но если мы получим правильно сформированный документ, мы создадим документ newPerson из модели Person и сохраним его в нашей БД с помощью функции newPerson.save () . Это определено в Mongoose и принимает обратный вызов в качестве аргумента. Этот обратный вызов имеет 2 аргумента — ошибка и ответ. Эти аргументы будут отображать представление show_message .
Чтобы показать ответ от этого маршрута, нам также нужно создать представление show_message . Создайте новый вид с помощью следующего кода —
html head title Person body if(type == "error") h3(style = "color:red") #{message} else h3 New person, name: #{person.name}, age: #{person.age} and nationality: #{person.nationality} added!
При успешной отправке формы мы получим следующий ответ (show_message.pug) —
Теперь у нас есть интерфейс для создания людей .
Получение документов
Mongoose предоставляет множество функций для извлечения документов, мы сосредоточимся на трех из них. Все эти функции также принимают обратный вызов в качестве последнего параметра, и, как и функция сохранения, их аргументы — это ошибка и ответ. Три функции заключаются в следующем —
Model.find (условия, обратный вызов)
Эта функция находит все документы, соответствующие полям в объекте условий. Те же операторы, которые используются в Mongo, также работают в mongoose. Например,
Person.find(function(err, response){ console.log(response); });
Это позволит получить все документы из коллекции человека.
Person.find({name: "Ayush", age: 20}, function(err, response){ console.log(response); });
При этом будут получены все документы, для которых поле имеет имя «Аюш» и возраст 20 лет.
Мы также можем предоставить необходимую проекцию, то есть поля, которые нам нужны. Например, если нам нужны только имена людей, национальность которых «индиец» , мы используем —
Person.find({nationality: "Indian"}, "name", function(err, response){ console.log(response); });
Model.findOne (условия, обратный вызов)
Эта функция всегда выбирает один, самый важный документ. Он имеет те же точные аргументы, что и Model.find () .
Model.findById (id, обратный вызов)
Эта функция принимает _id (определенный mongo) в качестве первого аргумента, необязательную строку проекции и обратный вызов для обработки ответа. Например,
Person.findById("507f1f77bcf86cd799439011", function(err, response){ console.log(response); });
Давайте теперь создадим маршрут для просмотра всех записей людей —
var express = require('express'); var app = express(); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my_db'); var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model("Person", personSchema); app.get('/people', function(req, res){ Person.find(function(err, response){ res.json(response); }); }); app.listen(3000);
Обновление документов
Mongoose предоставляет 3 функции для обновления документов. Функции описаны ниже —
Model.update (состояние, обновления, обратный вызов)
Эта функция принимает условия и обновляет объект в качестве входных данных и применяет изменения ко всем документам, соответствующим условиям в коллекции. Например, следующий код обновит национальность «американец» во всех документах Person —
Person.update({age: 25}, {nationality: "American"}, function(err, response){ console.log(response); });
Model.findOneAndUpdate (условие, обновления, обратный вызов)
Он находит один документ на основе запроса и обновляет его согласно второму аргументу. Он также принимает обратный вызов в качестве последнего аргумента. Давайте выполним следующий пример, чтобы понять функцию
Person.findOneAndUpdate({name: "Ayush"}, {age: 40}, function(err, response) { console.log(response); });
Model.findByIdAndUpdate (идентификатор, обновления, обратный вызов)
Эта функция обновляет один документ, идентифицируемый по его идентификатору. Например,
Person.findByIdAndUpdate("507f1f77bcf86cd799439011", {name: "James"}, function(err, response){ console.log(response); });
Давайте теперь создадим маршрут для обновления людей. Это будет маршрут PUT с идентификатором в качестве параметра и деталями в полезной нагрузке.
var express = require('express'); var app = express(); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my_db'); var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model("Person", personSchema); app.put('/people/:id', function(req, res){ Person.findByIdAndUpdate(req.params.id, req.body, function(err, response){ if(err) res.json({message: "Error in updating person with id " + req.params.id}); res.json(response); }); }); app.listen(3000);
Чтобы проверить этот маршрут, введите в своем терминале следующее (замените идентификатор на идентификатор из созданных вами людей ) —
curl -X PUT --data "name = James&age = 20&nationality = American "http://localhost:3000/people/507f1f77bcf86cd799439011
Это обновит документ, связанный с идентификатором, указанным в маршруте, с указанными выше деталями.
Удаление документов
Мы рассмотрели создание, чтение и обновление , теперь мы увидим, как Mongoose можно использовать для удаления документов. У нас есть 3 функции здесь, точно так же, как обновление.
Model.remove (условие, [обратный вызов])
Эта функция принимает объект условия в качестве входных данных и удаляет все документы, соответствующие условиям. Например, если нам нужно удалить всех людей в возрасте 20 лет, используйте следующий синтаксис:
Person.remove({age:20});
Model.findOneAndRemove (условие, [обратный вызов])
Эта функция удаляет один , наиболее релевантный документ в соответствии с объектом условий. Давайте выполним следующий код, чтобы понять то же самое.
Person.findOneAndRemove({name: "Ayush"});
Model.findByIdAndRemove (id, [callback])
Эта функция удаляет один документ, идентифицируемый по его идентификатору. Например,
Person.findByIdAndRemove("507f1f77bcf86cd799439011");
Давайте теперь создадим маршрут для удаления людей из нашей базы данных.
var express = require('express'); var app = express(); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/my_db'); var personSchema = mongoose.Schema({ name: String, age: Number, nationality: String }); var Person = mongoose.model("Person", personSchema); app.delete('/people/:id', function(req, res){ Person.findByIdAndRemove(req.params.id, function(err, response){ if(err) res.json({message: "Error in deleting record id " + req.params.id}); else res.json({message: "Person with id " + req.params.id + " removed."}); }); }); app.listen(3000);
Чтобы проверить вывод, используйте следующую команду curl —
curl -X DELETE http://localhost:3000/people/507f1f77bcf86cd799439011
Это удалит человека с указанным идентификатором, выдающего следующее сообщение —
{message: "Person with id 507f1f77bcf86cd799439011 removed."}
Это завершает, как мы можем создавать простые приложения CRUD, используя MongoDB, Mongoose и Express. Чтобы узнать больше о Mongoose, прочитайте документацию по API.
ExpressJS — Cookies
Файлы cookie — это простые небольшие файлы / данные, которые отправляются клиенту по запросу сервера и хранятся на стороне клиента. Каждый раз, когда пользователь загружает сайт обратно, этот файл cookie отправляется вместе с запросом. Это помогает нам отслеживать действия пользователя.
Ниже приведены многочисленные примеры использования файлов cookie HTTP.
- Управление сессиями
- Персонализация (системы рекомендаций)
- Отслеживание пользователей
Чтобы использовать куки с Express, нам нужно промежуточное программное обеспечение парсера файлов cookie. Чтобы установить его, используйте следующий код —
npm install --save cookie-parser
Теперь, чтобы использовать куки с Express, нам потребуется cookie-парсер . cookie-parser — это промежуточное ПО, которое анализирует куки-файлы, прикрепленные к объекту запроса клиента . Чтобы использовать его, нам потребуется это в нашем файле index.js ; это можно использовать так же, как мы используем другое промежуточное программное обеспечение. Здесь мы будем использовать следующий код.
var cookieParser = require('cookie-parser'); app.use(cookieParser());
cookie-анализатор анализирует заголовок Cookie и заполняет req.cookies объектом, обозначенным именами cookie. Чтобы установить новый файл cookie, давайте определим новый маршрут в вашем приложении Express, например:
var express = require('express'); var app = express(); app.get('/', function(req, res){ res.cookie('name', 'express').send('cookie set'); //Sets name = express }); app.listen(3000);
Чтобы проверить, установлен ваш cookie или нет, просто зайдите в браузер, запустите консоль и введите —
console.log(document.cookie);
Вы получите вывод, как (у вас может быть больше куки, возможно, из-за расширений в вашем браузере) —
"name = express"
Браузер также отправляет файлы cookie каждый раз, когда запрашивает сервер. Чтобы просмотреть файлы cookie с вашего сервера, на консоли сервера в маршруте добавьте следующий код к этому маршруту.
console.log('Cookies: ', req.cookies);
В следующий раз, когда вы отправите запрос по этому маршруту, вы получите следующий вывод.
Cookies: { name: 'express' }
Добавление файлов cookie со сроком действия
Вы можете добавить куки, срок действия которых истекает. Чтобы добавить cookie, срок действия которого истекает, просто передайте объект со свойством expire, установленным на время, когда вы хотите, чтобы срок его действия истек. Например,
//Expires after 360000 ms from the time it is set. res.cookie(name, 'value', {expire: 360000 + Date.now()});
Другой способ установить время истечения — использовать свойство maxAge . Используя это свойство, мы можем указать относительное время вместо абсолютного. Ниже приведен пример этого метода.
//This cookie also expires after 360000 ms from the time it is set. res.cookie(name, 'value', {maxAge: 360000});
Удаление существующих файлов cookie
Чтобы удалить cookie, используйте функцию clearCookie. Например, если вам нужно очистить файл cookie с именем foo , используйте следующий код.
var express = require('express'); var app = express(); app.get('/clear_cookie_foo', function(req, res){ res.clearCookie('foo'); res.send('cookie foo cleared'); }); app.listen(3000);
В следующей главе мы увидим, как использовать куки для управления сессиями.
ExpressJS — Сессии
HTTP не имеет состояния; Чтобы связать запрос с любым другим запросом, вам нужен способ хранения пользовательских данных между HTTP-запросами. Файлы cookie и параметры URL являются подходящими способами передачи данных между клиентом и сервером. Но они оба читабельны и на стороне клиента. Сессии решают именно эту проблему. Вы назначаете клиенту идентификатор, и он делает все дальнейшие запросы, используя этот идентификатор. Информация, связанная с клиентом, хранится на сервере, связанном с этим идентификатором.
Нам понадобится Express-сессия , поэтому установите его, используя следующий код.
npm install --save express-session
Мы установим промежуточное программное обеспечение для сессии и cookie-парсера . В этом примере мы будем использовать хранилище по умолчанию для хранения сессий, то есть MemoryStore. Никогда не используйте это в производственных условиях. Промежуточное программное обеспечение сеанса обрабатывает все для нас, т.е. создает сеанс, устанавливает cookie сеанса и создает объект сеанса в объекте req .
Всякий раз, когда мы делаем запрос от того же клиента снова, мы будем хранить информацию об их сеансе у нас (учитывая, что сервер не был перезапущен). Мы можем добавить больше свойств к объекту сеанса. В следующем примере мы создадим счетчик просмотров для клиента.
var express = require('express'); var cookieParser = require('cookie-parser'); var session = require('express-session'); var app = express(); app.use(cookieParser()); app.use(session({secret: "Shh, its a secret!"})); app.get('/', function(req, res){ if(req.session.page_views){ req.session.page_views++; res.send("You visited this page " + req.session.page_views + " times"); } else { req.session.page_views = 1; res.send("Welcome to this page for the first time!"); } }); app.listen(3000);
Код выше, когда пользователь посещает сайт, создает новый сеанс для пользователя и назначает ему cookie. В следующий раз, когда пользователь приходит, cookie проверяется, и переменная сеанса page_view обновляется соответственно.
Теперь, если вы запустите приложение и перейдете на localhost: 3000 , будет отображен следующий вывод.
Если вы вернетесь на страницу, счетчик страниц увеличится. Страница на следующем скриншоте обновлялась 42 раза.
ExpressJS — Аутентификация
Аутентификация — это процесс, в котором предоставленные учетные данные сравниваются с данными в файле в базе данных авторизованных пользователей в локальной операционной системе или на сервере аутентификации. Если учетные данные совпадают, процесс завершается, и пользователю предоставляется авторизация для доступа.
Чтобы создать систему аутентификации, нам нужно создать страницу регистрации и хранилище паролей пользователей. Следующий код создает для нас учетную запись и сохраняет ее в памяти. Это только для демонстрации; рекомендуется, чтобы постоянное хранилище (база данных или файлы) всегда использовалось для хранения пользовательской информации.
var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var multer = require('multer'); var upload = multer(); var session = require('express-session'); var cookieParser = require('cookie-parser'); app.set('view engine', 'pug'); app.set('views','./views'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(upload.array()); app.use(cookieParser()); app.use(session({secret: "Your secret key"})); var Users = []; app.get('/signup', function(req, res){ res.render('signup'); }); app.post('/signup', function(req, res){ if(!req.body.id || !req.body.password){ res.status("400"); res.send("Invalid details!"); } else { Users.filter(function(user){ if(user.id === req.body.id){ res.render('signup', { message: "User Already Exists! Login or choose another user id"}); } }); var newUser = {id: req.body.id, password: req.body.password}; Users.push(newUser); req.session.user = newUser; res.redirect('/protected_page'); } }); app.listen(3000);
Теперь для формы регистрации создайте новое представление с именем signup.jade.
SIGNUP.JADE
html head title Signup body if(message) h4 #{message} form(action = "/signup" method = "POST") input(name = "id" type = "text" required placeholder = "User ID") input(name = "password" type = "password" required placeholder = "Password") button(type = "Submit") Sign me up!
Проверьте, загружается ли эта страница, посетив localhost: 3000 / регистрация.
Мы установили обязательный атрибут для обоих полей, поэтому браузеры с поддержкой HTML5 не позволят нам отправить эту форму, пока мы не предоставим и идентификатор, и пароль. Если кто-то попытается зарегистрироваться, используя запрос скручивания без идентификатора пользователя или пароля, появится сообщение об ошибке. Создайте новый файл с именем protected_page.pug в представлениях со следующим содержанием —
html head title Protected page body div Hey #{id}, How are you doing today? div Want to log out? div Logout
Эта страница должна быть видимой, только если пользователь только что зарегистрировался или вошел в систему. Теперь давайте определим его маршрут, а также маршруты для входа и выхода —
var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var multer = require('multer'); var upload = multer(); var session = require('express-session'); var cookieParser = require('cookie-parser'); app.set('view engine', 'pug'); app.set('views','./views'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(upload.array()); app.use(cookieParser()); app.use(session({secret: "Your secret key"})); var Users = []; app.get('/signup', function(req, res){ res.render('signup'); }); app.post('/signup', function(req, res){ if(!req.body.id || !req.body.password){ res.status("400"); res.send("Invalid details!"); } else { Users.filter(function(user){ if(user.id === req.body.id){ res.render('signup', { message: "User Already Exists! Login or choose another user id"}); } }); var newUser = {id: req.body.id, password: req.body.password}; Users.push(newUser); req.session.user = newUser; res.redirect('/protected_page'); } }); function checkSignIn(req, res){ if(req.session.user){ next(); //If session exists, proceed to page } else { var err = new Error("Not logged in!"); console.log(req.session.user); next(err); //Error, trying to access unauthorized page! } } app.get('/protected_page', checkSignIn, function(req, res){ res.render('protected_page', {id: req.session.user.id}) }); app.get('/login', function(req, res){ res.render('login'); }); app.post('/login', function(req, res){ console.log(Users); if(!req.body.id || !req.body.password){ res.render('login', {message: "Please enter both id and password"}); } else { Users.filter(function(user){ if(user.id === req.body.id && user.password === req.body.password){ req.session.user = user; res.redirect('/protected_page'); } }); res.render('login', {message: "Invalid credentials!"}); } }); app.get('/logout', function(req, res){ req.session.destroy(function(){ console.log("user logged out.") }); res.redirect('/login'); }); app.use('/protected_page', function(err, req, res, next){ console.log(err); //User should be authenticated! Redirect him to log in. res.redirect('/login'); }); app.listen(3000);
Мы создали функцию промежуточного программного обеспечения checkSignIn, чтобы проверить, вошел ли пользователь в систему. Защищенная_страница использует эту функцию. Чтобы выйти из системы, мы уничтожаем сессию.
Давайте теперь создадим страницу входа. Назовите представление как login.pug и введите содержимое —
html head title Signup body if(message) h4 #{message} form(action = "/login" method = "POST") input(name = "id" type = "text" required placeholder = "User ID") input(name = "password" type = "password" required placeholder = "Password") button(type = "Submit") Log in
Наше простое приложение для аутентификации завершено; давайте теперь протестируем приложение. Запустите приложение, используя nodemon index.js , и перейдите к localhost: 3000 / signup.
Введите имя пользователя и пароль и нажмите «Зарегистрироваться». Вы будете перенаправлены на страницу protected_page, если данные верны / уникальны —
Теперь выйдите из приложения. Это перенаправит нас на страницу входа —
Этот маршрут защищен таким образом, что если неаутентифицированный человек попытается его посетить, он будет перенаправлен на нашу страницу входа. Это все о базовой аутентификации пользователя. Всегда рекомендуется использовать постоянную систему сеансов и использовать хеши для передачи пароля. Сейчас есть намного лучшие способы аутентификации пользователей, использующие токены JSON.
ExpressJS — RESTFul API
API всегда необходим для создания мобильных приложений, одностраничных приложений, использования вызовов AJAX и предоставления данных клиентам. Популярный архитектурный стиль структурирования и именования этих API-интерфейсов и конечных точек называется REST (репрезентативное состояние передачи) . HTTP 1.1 был разработан с учетом принципов REST. REST был представлен Роем Филдингом в 2000 году в его «Бумажной диссертации».
RESTful URI и методы предоставляют нам практически всю информацию, необходимую для обработки запроса. Таблица, приведенная ниже, суммирует, как должны использоваться различные глаголы и как должны называться URI. Мы будем создавать API фильмов к концу; давайте теперь обсудим, как это будет структурировано.
метод | URI | подробности | функция |
---|---|---|---|
ПОЛУЧИТЬ | /фильмы | Безопасный, кэшируемый | Получает список всех фильмов и их детали |
ПОЛУЧИТЬ | / Фильмы / 1234 | Безопасный, кэшируемый | Получает подробную информацию о фильме id 1234 |
СООБЩЕНИЕ | /фильмы | N / A | Создает новый фильм с предоставленной информацией. Ответ содержит URI для этого вновь созданного ресурса. |
ПОЛОЖИЛ | / Фильмы / 1234 | идемпотент | Изменяет идентификатор фильма 1234 (создает его, если он еще не существует). Ответ содержит URI для этого вновь созданного ресурса. |
УДАЛЯТЬ | / Фильмы / 1234 | идемпотент | Идентификатор фильма 1234 следует удалить, если он существует. Ответ должен содержать статус запроса. |
УДАЛИТЬ или ПОСТАВИТЬ | /фильмы | Недействительным | Должен быть недействительным. DELETE и PUT должны указывать, над каким ресурсом они работают. |
Давайте теперь создадим этот API в Express. Мы будем использовать JSON в качестве нашего транспортного формата данных, так как с ним легко работать в JavaScript и есть другие преимущества. Замените файл index.js на файл movies.js, как показано в следующей программе.
index.js
var express = require('express'); var bodyParser = require('body-parser'); var multer = require('multer'); var upload = multer(); var app = express(); app.use(cookieParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(upload.array()); //Require the Router we defined in movies.js var movies = require('./movies.js'); //Use the Router on the sub route /movies app.use('/movies', movies); app.listen(3000);
Теперь, когда мы настроили наше приложение, давайте сосредоточимся на создании API.
Начните с настройки файла movies.js. Мы не используем базу данных для хранения фильмов, а храним их в памяти; поэтому каждый раз, когда сервер перезагружается, добавленные нами фильмы исчезают. Это можно легко имитировать с помощью базы данных или файла (с помощью модуля node fs).
После того, как вы импортируете Express, создайте маршрутизатор и экспортируйте его, используя module.exports —
var express = require('express'); var router = express.Router(); var movies = [ {id: 101, name: "Fight Club", year: 1999, rating: 8.1}, {id: 102, name: "Inception", year: 2010, rating: 8.7}, {id: 103, name: "The Dark Knight", year: 2008, rating: 9}, {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9} ]; //Routes will go here module.exports = router;
ПОЛУЧИТЬ маршруты
Давайте определим маршрут GET для получения всех фильмов —
router.get('/', function(req, res){ res.json(movies); });
Чтобы проверить, работает ли это нормально, запустите ваше приложение, затем откройте терминал и введите —
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/movies
Следующий ответ будет отображаться —
[{"id":101,"name":"Fight Club","year":1999,"rating":8.1}, {"id":102,"name":"Inception","year":2010,"rating":8.7}, {"id":103,"name":"The Dark Knight","year":2008,"rating":9}, {"id":104,"name":"12 Angry Men","year":1957,"rating":8.9}]
У нас есть маршрут, чтобы получить все фильмы. Теперь давайте создадим маршрут для получения конкретного фильма по его идентификатору.
router.get('/:id([0-9]{3,})', function(req, res){ var currMovie = movies.filter(function(movie){ if(movie.id == req.params.id){ return true; } }); if(currMovie.length == 1){ res.json(currMovie[0]) } else { res.status(404);//Set status to 404 as movie was not found res.json({message: "Not Found"}); } });
Это даст нам фильмы в соответствии с идентификатором, который мы предоставили. Чтобы проверить вывод, используйте следующую команду в вашем терминале —
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/movies/101
Вы получите следующий ответ —
{"id":101,"name":"Fight Club","year":1999,"rating":8.1}
Если вы посещаете неверный маршрут, он выдаст ошибку not GET, а если вы посетите действующий маршрут с идентификатором, который не существует, он выдаст ошибку 404.
Мы закончили с маршрутами GET, теперь давайте перейдем к маршруту POST .
POST маршрут
Используйте следующий маршрут для обработки POST- данных —
router.post('/', function(req, res){ //Check if all fields are provided and are valid: if(!req.body.name || !req.body.year.toString().match(/^[0-9]{4}$/g) || !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){ res.status(400); res.json({message: "Bad Request"}); } else { var newId = movies[movies.length-1].id+1; movies.push({ id: newId, name: req.body.name, year: req.body.year, rating: req.body.rating }); res.json({message: "New movie created.", location: "/movies/" + newId}); } });
Это создаст новый фильм и сохранит его в переменной movies. Чтобы проверить этот маршрут, введите следующий код в своем терминале —
curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" http://localhost:3000/movies
Следующий ответ будет отображаться —
{"message":"New movie created.","location":"/movies/105"}
Чтобы проверить, было ли это добавлено к объекту movies, снова запустите запрос get для / movies / 105 . Следующий ответ будет отображаться —
{"id":105,"name":"Toy story","year":"1995","rating":"8.5"}
Давайте перейдем к созданию маршрутов PUT и DELETE.
PUT маршрут
Маршрут PUT почти совпадает с маршрутом POST. Мы будем указывать идентификатор для объекта, который будет обновлен / создан. Создайте маршрут следующим образом.
router.put('/:id', function(req, res){ //Check if all fields are provided and are valid: if(!req.body.name || !req.body.year.toString().match(/^[0-9]{4}$/g) || !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) || !req.params.id.toString().match(/^[0-9]{3,}$/g)){ res.status(400); res.json({message: "Bad Request"}); } else { //Gets us the index of movie with given id. var updateIndex = movies.map(function(movie){ return movie.id; }).indexOf(parseInt(req.params.id)); if(updateIndex === -1){ //Movie not found, create new movies.push({ id: req.params.id, name: req.body.name, year: req.body.year, rating: req.body.rating }); res.json({message: "New movie created.", location: "/movies/" + req.params.id}); } else { //Update existing movie movies[updateIndex] = { id: req.params.id, name: req.body.name, year: req.body.year, rating: req.body.rating }; res.json({message: "Movie id " + req.params.id + " updated.", location: "/movies/" + req.params.id}); } } });
Этот маршрут будет выполнять функцию, указанную в таблице выше. Он обновит объект новыми деталями, если он существует. Если он не существует, он создаст новый объект. Чтобы проверить маршрут, используйте следующую команду curl. Это обновит существующий фильм. Чтобы создать новый фильм, просто измените идентификатор на несуществующий идентификатор.
curl -X PUT --data "name = Toy%20story&year = 1995&rating = 8.5" http://localhost:3000/movies/101
отклик
{"message":"Movie id 101 updated.","location":"/movies/101"}
УДАЛИТЬ маршрут
Используйте следующий код для создания маршрута удаления. —
router.delete('/:id', function(req, res){ var removeIndex = movies.map(function(movie){ return movie.id; }).indexOf(req.params.id); //Gets us the index of movie with given id. if(removeIndex === -1){ res.json({message: "Not found"}); } else { movies.splice(removeIndex, 1); res.send({message: "Movie id " + req.params.id + " removed."}); } });
Проверьте маршрут так же, как мы проверяли другие маршруты. При успешном удалении (например, с идентификатором 105) вы получите следующий вывод:
{message: "Movie id 105 removed."}
Наконец, наш файл movies.js будет выглядеть следующим образом.
var express = require('express'); var router = express.Router(); var movies = [ {id: 101, name: "Fight Club", year: 1999, rating: 8.1}, {id: 102, name: "Inception", year: 2010, rating: 8.7}, {id: 103, name: "The Dark Knight", year: 2008, rating: 9}, {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9} ]; router.get('/:id([0-9]{3,})', function(req, res){ var currMovie = movies.filter(function(movie){ if(movie.id == req.params.id){ return true; } }); if(currMovie.length == 1){ res.json(currMovie[0]) } else { res.status(404); //Set status to 404 as movie was not found res.json({message: "Not Found"}); } }); router.post('/', function(req, res){ //Check if all fields are provided and are valid: if(!req.body.name || !req.body.year.toString().match(/^[0-9]{4}$/g) || !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){ res.status(400); res.json({message: "Bad Request"}); } else { var newId = movies[movies.length-1].id+1; movies.push({ id: newId, name: req.body.name, year: req.body.year, rating: req.body.rating }); res.json({message: "New movie created.", location: "/movies/" + newId}); } }); router.put('/:id', function(req, res) { //Check if all fields are provided and are valid: if(!req.body.name || !req.body.year.toString().match(/^[0-9]{4}$/g) || !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) || !req.params.id.toString().match(/^[0-9]{3,}$/g)){ res.status(400); res.json({message: "Bad Request"}); } else { //Gets us the index of movie with given id. var updateIndex = movies.map(function(movie){ return movie.id; }).indexOf(parseInt(req.params.id)); if(updateIndex === -1){ //Movie not found, create new movies.push({ id: req.params.id, name: req.body.name, year: req.body.year, rating: req.body.rating }); res.json({ message: "New movie created.", location: "/movies/" + req.params.id}); } else { //Update existing movie movies[updateIndex] = { id: req.params.id, name: req.body.name, year: req.body.year, rating: req.body.rating }; res.json({message: "Movie id " + req.params.id + " updated.", location: "/movies/" + req.params.id}); } } }); router.delete('/:id', function(req, res){ var removeIndex = movies.map(function(movie){ return movie.id; }).indexOf(req.params.id); //Gets us the index of movie with given id. if(removeIndex === -1){ res.json({message: "Not found"}); } else { movies.splice(removeIndex, 1); res.send({message: "Movie id " + req.params.id + " removed."}); } }); module.exports = router;
Это завершает наш REST API. Теперь вы можете создавать гораздо более сложные приложения, используя этот простой архитектурный стиль и Express.
ExpressJS — Строительные леса
Скаффолдинг позволяет нам легко создавать каркас для веб-приложения . Мы вручную создаем наш публичный каталог, добавляем промежуточное программное обеспечение, создаем отдельные файлы маршрутов и т. Д. Инструмент скаффолдинга настраивает все эти вещи для нас, чтобы мы могли непосредственно приступить к созданию нашего приложения.
Подмости, которые мы будем использовать, называются Yeoman . Это инструмент для скаффолдинга, созданный для Node.js, но также имеющий генераторы для нескольких других фреймворков (таких как flask, rails, django и т. Д.). Чтобы установить Yeoman, введите следующую команду в своем терминале —
npm install -g yeoman
Yeoman использует генераторы для создания приложений. Чтобы проверить генераторы, доступные на npm для использования с Yeoman, вы можете нажать на эту ссылку . В этом уроке мы будем использовать «генератор-экспресс-простой» . Чтобы установить этот генератор, введите следующую команду в своем терминале —
npm install -g generator-express-simple
Чтобы использовать этот генератор, введите следующую команду —
yo express-simple test-app
Вам будет задано несколько простых вопросов, например, какие вещи вы хотите использовать в своем приложении. Выберите следующие ответы, или, если вы уже знаете об этих технологиях, затем выберите, какими они должны быть.
express-simple comes with bootstrap and jquery [?] Select the express version you want: 4.x [?] Do you want an mvc express app: Yes [?] Select the css preprocessor you would like to use: sass [?] Select view engine you would like to use: jade [?] Select the build tool you want to use for this project: gulp [?] Select the build tool you want to use for this project: gulp [?] Select the language you want to use for the build tool: javascript create public/sass/styles.scss create public/js/main.js create views/layout.jade create views/index.jade create views/404.jade create app.js create config.js create routes/index.js create package.json create bower.json identical .bowerrc identical .editorconfig identical .gitignore identical .jshintrc create gulpfile.js I'm all done. Running bower install & npm install for you to install the required dependencies. If this fails, try running the command yourself.
Затем он создаст новое приложение для вас, установит все зависимости, добавит несколько страниц в ваше приложение (домашняя страница, страница 404 не найдена и т. Д.) И предоставит вам структуру каталогов для работы.
Этот генератор создает для нас очень простую структуру. Изучите множество генераторов, доступных для Express, и выберите тот, который вам подходит. Шаги для работы со всеми генераторами одинаковы. Вам нужно будет установить генератор, запустить его с помощью Yeoman; он задаст вам несколько вопросов, а затем создаст каркас для вашего приложения на основе ваших ответов.
ExpressJS — Обработка ошибок
Обработка ошибок в Express выполняется с использованием промежуточного программного обеспечения. Но это промежуточное ПО обладает особыми свойствами. Промежуточное программное обеспечение для обработки ошибок определяется так же, как и другие функции промежуточного программного обеспечения, за исключением того, что функции обработки ошибок ДОЛЖНЫ иметь четыре аргумента вместо трех — err, req, res, next . Например, чтобы отправить ответ на любую ошибку, мы можем использовать —
app.use(function(err, req, res, next) { console.error(err.stack); res.status(500).send('Something broke!'); });
До сих пор мы обрабатывали ошибки в самих маршрутах. Промежуточное программное обеспечение для обработки ошибок позволяет нам отделить нашу логику ошибок и соответственно отправлять ответы. Метод next (), который мы обсуждали в промежуточном ПО, приводит нас к следующему обработчику промежуточного ПО / маршрута .
Для обработки ошибок у нас есть следующая (err) функция. Вызов этой функции пропускает все промежуточное программное обеспечение и сопоставляет нас со следующим обработчиком ошибок для этого маршрута. Позвольте нам понять это на примере.
var express = require('express'); var app = express(); app.get('/', function(req, res){ //Create an error and pass it to the next function var err = new Error("Something went wrong"); next(err); }); /* * other route handlers and middleware here * .... */ //An error handling middleware app.use(function(err, req, res, next) { res.status(500); res.send("Oops, something went wrong.") }); app.listen(3000);
Это промежуточное программное обеспечение для обработки ошибок может быть стратегически размещено после маршрутов или содержать условия для обнаружения типов ошибок и соответственно реагировать на запросы клиентов. Вышеуказанная программа отобразит следующий вывод.
ExpressJS — отладка
Express использует модуль Debug для внутренней регистрации информации о сопоставлении маршрутов, функциях промежуточного программного обеспечения, режиме приложений и т. Д.
Чтобы увидеть все внутренние журналы, используемые в Express, установите для переменной среды DEBUG значение Express: * при запуске приложения —
DEBUG = express:* node index.js
Будет отображен следующий вывод.
Эти журналы очень полезны, когда компонент вашего приложения работает неправильно. Этот подробный вывод может быть немного ошеломляющим. Вы также можете ограничить переменную DEBUG определенной областью, которую нужно зарегистрировать. Например, если вы хотите ограничить регистратор приложением и маршрутизатором, вы можете использовать следующий код.
DEBUG = express:application,express:router node index.js
Отладка отключена по умолчанию и автоматически включается в производственной среде. Отладка также может быть расширена в соответствии с вашими потребностями, вы можете прочитать больше об этом на странице npm.
ExpressJS — лучшие практики
В отличие от Django и Rails, у которых есть определенный способ работы, структура файла и т. Д., Express не следует определенному пути. Это означает, что вы можете структурировать приложение так, как вам нравится. Но по мере увеличения размера вашего приложения его очень сложно поддерживать, если оно не имеет четко определенной структуры. В этой главе мы рассмотрим обычно используемые структуры каталогов и разделение задач при создании наших приложений.
Сначала мы обсудим лучшие практики создания приложений для узлов и Express.
-
Всегда начинайте проект узла, используя npm init .
-
Всегда устанавливайте зависимости с помощью —save или —save-dev . Это гарантирует, что если вы перейдете на другую платформу, вы можете просто запустить npm install для установки всех зависимостей.
-
Придерживайтесь строчных имен файлов и переменных camelCase. Если вы посмотрите на любой модуль npm, он назван в нижнем регистре и разделен черточками. Всякий раз, когда вам нужны эти модули, используйте camelCase.
-
Не добавляйте node_modules в свои репозитории. Вместо этого npm устанавливает все на машины для разработки.
-
Используйте файл конфигурации для хранения переменных
-
Группируйте и изолируйте маршруты в своем собственном файле. Например, возьмем операции CRUD в примере фильмов, которые мы видели на странице API REST.
Всегда начинайте проект узла, используя npm init .
Всегда устанавливайте зависимости с помощью —save или —save-dev . Это гарантирует, что если вы перейдете на другую платформу, вы можете просто запустить npm install для установки всех зависимостей.
Придерживайтесь строчных имен файлов и переменных camelCase. Если вы посмотрите на любой модуль npm, он назван в нижнем регистре и разделен черточками. Всякий раз, когда вам нужны эти модули, используйте camelCase.
Не добавляйте node_modules в свои репозитории. Вместо этого npm устанавливает все на машины для разработки.
Используйте файл конфигурации для хранения переменных
Группируйте и изолируйте маршруты в своем собственном файле. Например, возьмем операции CRUD в примере фильмов, которые мы видели на странице API REST.
Структура каталогов
Давайте теперь обсудим Экспресс-структуру каталогов.
Веб-сайты
Express не имеет определенной сообществом структуры для создания приложений. Ниже приводится основная структура проекта для веб-сайта.
test-project/ node_modules/ config/ db.js //Database connection and configuration credentials.js //Passwords/API keys for external services used by your app config.js //Other environment variables models/ //For mongoose schemas users.js things.js routes/ //All routes for different entities in different files users.js things.js views/ index.pug 404.pug ... public/ //All static content being served images/ css/ javascript/ app.js routes.js //Require all routes in this and then require this file in app.js package.json
Существуют и другие подходы к созданию сайтов с помощью Express. Вы можете создать сайт, используя шаблон проектирования MVC. Для получения дополнительной информации вы можете посетить следующие ссылки.
https://code.tutsplus.com/tutorials/build-a-complete-mvc-website-with-expressjs—net-34168
а также,
https://www.terlici.com/2014/08/25/best-practices-express-structure.html .
RESTful API
API проще в разработке; им не нужен общедоступный каталог или каталог представлений. Используйте следующую структуру для создания API —
test-project/ node_modules/ config/ db.js //Database connection and configuration credentials.js //Passwords/API keys for external services used by your app models/ //For mongoose schemas users.js things.js routes/ //All routes for different entities in different files users.js things.js app.js routes.js //Require all routes in this and then require this file in app.js package.json
Вы также можете использовать генератор йоменов, чтобы получить аналогичную структуру.
ExpressJS — Ресурсы
В этой главе перечислены различные ресурсы, которые мы использовали для этого урока.
Самая важная ссылка — это, конечно, документы Express API — https://expressjs.com/en/4x/api.html.
Руководства, представленные на сайте Express по различным аспектам, также весьма полезны —
Список полезных книг и блогов по Express доступен по адресу https://expressjs.com/en/resources/books-blogs.html.
Список наиболее часто используемого промежуточного программного обеспечения с Express доступен по адресу https://expressjs.com/en/resources/middleware.html.
Эти блоги с советами и советами по Express могут оказаться полезными —
https://derickbailey.com/categories/tips-and-tricks/
https://scotch.io/tutorials/learn-to-use-the-new-router-in+-expressjs-4
Структура приложения — https://www.terlici.com/2014/08/25/best-practices-express-structure.html
RESTful APIs —
https://www.thepolyglotdeveloper.com/2015/10/create-a-simple-restful-api-with-node-js/
https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
https://devcenter.heroku.com/articles/mean-apps-restful-api
https://pixelhandler.com/posts/develop-a-restful-api-using-nodejs-with-express-and-mongoose
http://cwbuecheler.com/web/tutorials/2014/restful-web-app-node-express-mongodb/
Для расширенной аутентификации используйте PassportJS — http://passportjs.org