Единая функция обработки запросов собственного Node неизбежно будет становиться все более и более сложной в обслуживании по мере расширения функции. Платформа Express может сократить функции обработки в соответствии с модулями и функциями с помощью промежуточного программного обеспечения. Этот разделенный модуль не только логически ясен, но, что более важно, он очень удобен для дальнейшего обслуживания и разработки.
В этой статье подробно рассказывается об использовании Express, основное содержание которой включает:
- Что такое промежуточное ПО?
- Стек промежуточного программного обеспечения и рабочий процесс для обработки запросов.
- Использование промежуточного программного обеспечения.
- Как реализовать собственное промежуточное ПО.
- Стороннее промежуточное ПО, обычно используемое в Express.
Я надеюсь, что после прочтения этой статьи вы сможете получить более четкое представление об основных компонентах этого экспресса.
Промежуточное ПО и стек промежуточного ПО
Для всех веб-приложений его поток обработки можно просто описать как: прослушивание запросов, анализ запросов и ответ. Конечно, Node тоже следует этому процессу, но преобразует эти запросы в объекты JavaScript.
В отличие от собственного кода Node, Express разделяет последнюю часть приведенной выше диаграммы на набор функций промежуточного программного обеспечения (стек промежуточного ПО). Таким образом, рабочий процесс Express выглядит примерно так:
В отличие от чистого Node, функция стека промежуточного ПО в Express добавляет третий параметр в дополнение к параметрам, представляющим запрос и ответ. Параметр является функциональным объектом, по соглашению мы называем егоnext. Он используется для передачи потока обработки запроса стеком промежуточного программного обеспечения.
В потоке обработки всего стека промежуточного программного обеспечения необходимо вызвать хотя бы одну функцию.res.endМетод завершает обработку ответа. Далее мы углубим наше понимание стека промежуточного программного обеспечения, создав статическую файловую службу.
Пример: статический файловый сервер
Создайте папку и раздайте для нее статические файлы. В папке можно хранить любые файлы, например: HTML-файлы, картинки. В конце концов, все эти файлы будут доступны по сети через пример программы.
Функции примера программы примерно включают: может правильно вернуть существующий файл; вернуть ошибку 404, если файл не существует; распечатать все запросы доступа. Итак, стек промежуточного программного обеспечения для этого примера выглядит следующим образом:
- Промежуточное ПО для ведения журналов. Эта функция распечатает все сетевые запросы на терминале и перейдет к следующей функции промежуточного программного обеспечения после печати введения.
- Промежуточное ПО для отправки статических файлов. Возвращается клиенту, если доступный файл существует. Если файл не существует, он перейдет к промежуточному программному обеспечению обработки ошибок.
- 404 Промежуточное ПО обработки. Если файл не существует, промежуточное ПО отправит клиенту сообщение об ошибке 404.
Блок-схема выглядит следующим образом:
После выяснения целей и требований примера мы реализуем приведенный ниже код.
Готов к работе
Как и прежде, создайте новый каталог проекта и скопируйте следующее вpackage.jsonсередина:
{
"name": "static-file-fun",
"private": true,
"scripts": {
"start": "node app.js"
}
}
Далее выполняемnpm install express --saveУстановите последнюю версию Express. Убедитесь, что после завершения установки мы создаем новую папку в каталоге проектаstaticи хранить в нем несколько файлов. Наконец, мы создаем новый файл основной записи проекта.app.js. После того, как все на месте, примерный каталог проекта выглядит следующим образом:
Кроме того, указанное значение является причиной того, что конфигурацияnpm startКоманды, как из-за соглашений о разработке, так и, что более важно, для других, чтобы использовать их из коробки без необходимости вручную находить запись программы самостоятельно.
Первое промежуточное ПО: ведение журнала
Согласно схеме обработки, сформулированной выше, первое, что необходимо реализовать, — это ПО промежуточного слоя ведения журналов. Скопируйте следующий код в файл записиapp.jsсередина:
var express = require("express");
var path = require("path");
var fs = require("fs");
var app = express();
app.use(function(req, res, next) {
console.log("Request IP: " + req.url);
console.log("Request date: " + new Date());
});
app.listen(3000, function() {
console.log("App started on port 3000");
});
через вышеуказанноеapp.useмы успешно реализовали первую функцию в приложении, которая должна регистрировать каждый сетевой запрос. Конечно тут проблема, текущее приложение не отвечает на запрос. Это означает следующее: если вы используетеnpm startПоднимите сервис и получите доступloaclhost:3000Браузер будет зависать в ожидании ответа, пока не произойдет ошибка тайм-аута. Но не волнуйтесь, мы можем вызвать его в этом промежуточном программном обеспечении после выполнения следующих функций.next()Передайте задачу ответа последующему промежуточному ПО.
Здесь нам просто нужно понять: по идее, после того, как промежуточная функция закончила обработку, она должна выполнить один из следующих двух шагов.
- Вся обработка заканчивается, отправитьred.endили в экспрессred.sendFileПодождите, пока функция не закончит отвечать.
- перечислитьnextФункция выполняет следующую функцию промежуточного программного обеспечения.
Итак, здесь мы ставимnext()Вызов завершения упорядочивает логику промежуточного программного обеспечения журнала:
// ...
app.use(function(req, res, next) {
console.log("Request IP: " + req.url);
console.log("Request date: " + new Date());
next(); // 新的这行很重要
});
// ...
Перезапустите службу в этот момент и получите доступhttp://localhost:3000Если это так, запрос на доступ будет полностью зарегистрирован. Но поскольку программа не ответила, Express отправит клиенту сообщение об ошибке. Итак, далее мы завершим последующий процесс.
ПО промежуточного слоя для обслуживания статических файлов
Промежуточное программное обеспечение для обслуживания статических файлов должно иметь следующие функции:
- Проверьте, существует ли файл в каталоге
- Вызывается, если файл существуетres.sendFileЗавершить обработку ответа.
- Если файл не существует, продолжайте вызывать следующее промежуточное программное обеспечение с точки зрения кода, чтобы вызватьnext.
Среди них нам нужно использовать встроенныйpathмодуль указывает путь, затем использует встроенныйfsМодуль считает, что версия файла существует. Добавьте следующий код после ПО промежуточного слоя ведения журнала:
// 日志中间件
app.use(function(req, res, next) {
// …
});
app.use(function(req, res, next) {
var filePath = path.join(__dirname, "static", req.url);
fs.exists(filePath, function(exists) {
if (exists) {
res.sendFile(filePath);
} else {
next();
}
});
});
app.listen(3000, function() {
...
}
В промежуточном программном обеспечении мы сначала используемpath.joinПолный путь к объединенному файлу. Например, если пользователь получает доступhttp://localhost:3000/celine.mp3слова файлаreq.urlЗначение/celine.mp3Полный путь после сплайсинга"/path/to/your/project/static/celine.mp3".
Затем промежуточное ПО вызываетfs.existsФункция проверяет, существует ли файл. Происходит, если файл существует, в противном случае вызываетnext()Перейдите к следующему промежуточному программному обеспечению. Если доступный URL-адрес не имеет соответствующего файла, произойдет та же ошибка, что и раньше. Итак, последнее промежуточное ПО должно быть реализовано ниже: промежуточное ПО обработки 404.
404 Промежуточное ПО обработки
Задача промежуточного ПО 404 — отправить сообщение об ошибке 404, скопировать следующий код реализации и добавить его после промежуточного ПО статического сервиса:
app.use(function(req, res) {
// 设置状态码为404
res.status(404);
// 发送错误提示
res.send("File not found!");
});
// ...
Таким образом, весь проект завершен. Если вы снова запустите службу, предыдущая ошибка будет заменена ошибкой 404. Кроме того, если вы переместите функцию промежуточного программного обеспечения на первое место в стеке промежуточного программного обеспечения, вы обнаружите, что все запросы будут получать сообщение об ошибке 404. Это означает, что порядок функций в стеке промежуточного программного обеспечения очень важен.
сюда,app.jsПолный код выглядит следующим образом:
var express = require("express");
var path = require("path");
var fs = require("fs");
var app = express();
app.use(function(req, res, next) {
console.log("Request IP: " + req.url);
console.log("Request date: " + new Date());
next();
});
app.use(function(req, res, next) {
var filePath = path.join(__dirname, "static", req.url);
fs.stat(filePath, function(err, fileInfo) {
if (err) {
next();
return;
}
if (fileInfo.isFile()) {
res.sendFile(filePath);
} else {
next();
}
});
});
app.use(function(req, res) {
res.status(404);
res.send("File not found!");
});
app.listen(3000, function() {
console.log("App started on port 3000");
});
Конечно, это только предварительный код, и есть много мест, которые можно оптимизировать.
Замените промежуточное программное обеспечение ведения журнала на: Morgan
В разработке программного обеспечения, если лучшее решение вашей проблемы уже существует, идеальным будет использовать это решение напрямую, а не «изобретать велосипед». Итак, ниже мы используем мощныйMorganЗамените промежуточное программное обеспечение журнала, реализованное вами выше. Хотя это промежуточное ПО не является встроенным модулем Express, оно поддерживается и проверяется командой Express.
бегатьnpm install morgan --saveУстановите последнюю версию модуля Morgan. Затем используйте Morgan для замены предыдущего промежуточного программного обеспечения журнала:
var express = require("express");
var morgan = require("morgan");
...
var app = express();
app.use(morgan("short"));
...
Когда вы снова запустите службу и получите доступ к ресурсу, терминал выведет полезную информацию, включая IP-адрес:
в кодеmorganЭто функция, и ее возвращаемое значение является промежуточной функцией. Когда вы вызываете его, он возвращает промежуточное программное обеспечение ведения журнала, подобное тому, которое реализовано между ними. Чтобы сделать код более понятным, вы также можете переписать код следующим образом:
var morganMiddleware = morgan("short");
app.use(morganMiddleware);
Кроме того, здесь в вызывающей функции используется isshortкак выходной вариант. На самом деле модуль также предоставляет два других варианта вывода:combinedраспечатать максимум информации;tinyПечатать минимум информации.
В дополнение к замене исходного промежуточного программного обеспечения ведения журналов на Morgan мы также можем заменить предыдущую реализацию кода встроенным статическим промежуточным программным обеспечением.
Используйте встроенное промежуточное ПО Express для статических файлов.
Далее мы используем встроенный в Expressexpress.staticмодуль для замены предыдущего промежуточного ПО для статических файлов. Он работает так же, как предыдущий код промежуточного программного обеспечения, но имеет лучшую безопасность и производительность. Например, он реализует внутреннее кэширование ресурсов.
Как и Морган,express.staticВозвращаемое значение функции также является функцией промежуточного программного обеспечения. нам просто нужноexpress.staticФункция может указать параметр пути. код показывает, как показано ниже:
var staticPath = path.join(__dirname, "static"); // 设置静态文件的路径
app.use(express.static(staticPath)); // 使用express.static从静态路径提供服务
// ...
После завершения замены вы обнаружите, что код значительно проще, чем раньше, и в то же время функция сильнее, чем раньше. Кроме того, эти испытанные модули промежуточного программного обеспечения гораздо более функциональны и надежны, чем реализация их собственного кода. В настоящее времяapp.jsПолный код в:
var express = require("express");
var morgan = require("morgan");
var path = require("path");
var app = express();
app.use(morgan("short"));
var staticPath = path.join(__dirname, "static");
app.use(express.static(staticPath));
app.use(function(req, res) {
res.status(404);
res.send("File not found!");
});
app.listen(3000, function() {
console.log("App started on port 3000");
});
промежуточное ПО для обработки ошибок
Ранее я сказал, что звонюnext()Следующее промежуточное ПО будет выполнено по порядку. На самом деле реальность не так проста. На самом деле существует два типа промежуточного программного обеспечения Express.
До сих пор вы касались первого типа: обычных промежуточных функций с тремя аргументами (иногдаnextбудут игнорироваться и останутся только два параметра), что является общим шаблоном, используемым в большинстве программ.
Второй тип встречается очень редко: промежуточное ПО для обработки ошибок. Когда ваше приложение находится в режиме ошибки, все обычное промежуточное ПО будет пропущено, а промежуточное ПО экспресс-обработки ошибок будет выполнено напрямую. Чтобы войти в режим ошибки, просто вызовитеnextс параметром. Это соглашение для вызова объектов ошибок, например:next(new Error("Something bad happened!")).
Для промежуточного программного обеспечения обработки ошибок требуется четыре параметра, последние три из которых соответствуют обычной форме, а первый параметрnext(new Error("Something bad happened!"))Переданный объект Error. Вы можете использовать промежуточное ПО для обработки ошибок, как и обычное промежуточное ПО, например, вызывая res.end или next. Если вы вызываете с параметрамиnextПромежуточное ПО продолжит работу со следующим промежуточным ПО для обработки ошибок, в противном случае оно выйдет из режима ошибки и вызовет следующее обычное промежуточное ПО.
Предположим, теперь есть четыре промежуточных ПО, выстроенных последовательно, третье из которых — промежуточное ПО для обработки ошибок, а остальные — обычное промежуточное ПО. Если ошибок нет, поток должен быть:
Как показано выше, промежуточное ПО для обработки ошибок действует так, как если бы оно не существовало, когда ошибок не возникало. Однако, как только возникает ошибка, все нормальное промежуточное ПО пропускается, поэтому поток обработки будет таким:
Хотя Express не применяет его, обычно промежуточное программное обеспечение для обработки ошибок размещается в нижней части стека промежуточного программного обеспечения. Таким образом, все предыдущие регулярные ошибки промежуточного программного обеспечения будут перехватываться этим промежуточным программным обеспечением обработки ошибок.
Промежуточное ПО для обработки ошибок Express будет ловить толькоnextПроизошла ошибка, дляthrowИсключения, вызванные ключевыми словами, не обрабатываются. У Express есть собственный механизм защиты от этих исключений: при сбое запроса приложение возвращает ошибку 500, и вся служба продолжает работать. Однако такие исключения, как синтаксические ошибки, напрямую приводят к сбою службы.
Давайте теперь рассмотрим промежуточное ПО для обработки ошибок в Express на простом примере. Предположим, что любой запрос, сделанный приложением пользователю, выполняется черезres.sendFileСлучаются картинки с пользователем. код показывает, как показано ниже:
var express = require("express");
var path = require("path");
var app = express();
var filePath = path.join(__dirname, "celine.jpg");
app.use(function(req, res) {
res.sendFile(filePath);
});
app.listen(3000, function() {
console.log("App started on port 3000");
});
Вы можете видеть, что это упрощенная версия предыдущей статической подачи файлов, которая происходит для любого запроса.celine.jpgрисунок. Но что, если файл не существует или при чтении файла произошла ошибка? Это требует некоторого механизма для обработки такого рода ошибок исключения, и это причина существования промежуточного программного обеспечения для обработки ошибок.
Чтобы запустить обработку исключений, мыres.sendFileЗавершите функцию обратного вызова исключения. Эта функция обратного вызова будет выполнена после отправки файла, и в функции обратного вызова есть параметр, показывающий, был ли файл отправлен успешно или нет. Пример кода выглядит следующим образом:
res.sendFile(filePath, function(err) {
if (err) {
console.error("File failed to send.");
} else {
console.log("File sent!");
}
});
Конечно, помимо вывода информации об ошибке, мы также можем ввести промежуточную функцию обработки ошибок, вызвав исключение, и эта часть кода реализована следующим образом:
// ...
app.use(function(req, res, next) {
res.sendFile(filePath, function(err) {
if (err) {
next(new Error("Error sending file!"));
}
});
});
// ...
После срабатывания исключения следующим шагом является реализация промежуточного программного обеспечения для обработки ошибок.
Обычно мы сначала записываем сообщение об ошибке, и эта информация, как правило, не отображается пользователю. В конце концов, показ длинного фрагмента информации о вызовах стека JavaScript нетехническим пользователям может вызвать у них ненужную путаницу. В частности, как только эта информация станет доступной для хакеров, они смогут перепроектировать работу веб-сайта и создать информационный риск.
Ниже мы просто печатаем сообщение об ошибке в промежуточном программном обеспечении обработки, не выполняя никакой дальнейшей обработки. Оно похоже на предыдущее ПО промежуточного слоя, за исключением того, что оно печатает сообщение об ошибке вместо сообщения запроса. Скопируйте следующий код после всего обычного промежуточного ПО:
// ...
app.use(function(err, req, res, next) {
// 记录错误
console.error(err);
// 继续到下一个错误处理中间件
next(err);
});
// ...
Теперь при возникновении исключения в программе эти сообщения об ошибках будут записываться в консоль для последующего анализа. Конечно, здесь есть еще кое-что, о чем нужно позаботиться, например: ответ на запрос. Поместите следующий код после предыдущего промежуточного программного обеспечения:
// ...
app.use(function(err, req, res, next) {
// 设置状态码为500
res.status(500);
// 发送错误信息
res.send("Internal server error.");
});
// ...
Помните, что это ПО промежуточного слоя для обработки ошибок может бытьnextдля запуска. Для этого простого приложения, вероятно, не так много исключений и ошибок, которые могли бы вызвать промежуточное программное обеспечение для обработки ошибок. Но по мере роста вашего приложения вам необходимо тщательно тестировать его на наличие неправильного поведения. Если возникают исключения, вы должны правильно обрабатывать эти исключения, а не сбой программы.
Суммировать
В этой статье мы более подробно рассмотрели основной модуль Express: промежуточное ПО. К ним относятся:
- Концепции и рабочий процесс стека промежуточного программного обеспечения Express.
- Как написать пользовательские функции промежуточного программного обеспечения.
- Как написать промежуточное ПО для обработки ошибок.
- Использование общих модулей промежуточного программного обеспечения.
оригинальныйадрес