Учебники

Koa.js — Краткое руководство

Koa.js — Обзор

Платформа веб-приложений предоставляет вам простой API для создания веб-сайтов, веб-приложений и бэкэндов. Вам не нужно беспокоиться о протоколах низкого уровня, процессах и т. Д.

Что такое Коа?

Коа предоставляет минимальный интерфейс для создания приложений. Это очень маленькая структура (600 LoC), которая предоставляет необходимые инструменты для создания приложений и довольно гибкая. На npm доступно множество модулей для Koa, которые можно напрямую подключить к нему. Коа можно рассматривать как ядро ​​express.js без всяких наворотов.

Почему Коа?

Коа имеет небольшую площадь (600 лок) и представляет собой очень тонкий слой абстракции над узлом для создания приложений на стороне сервера. Он полностью подключаемый и имеет огромное сообщество. Это также позволяет нам легко расширять Koa и использовать его в соответствии с нашими потребностями. Он построен с использованием передовой технологии (ES6), которая дает ему преимущество перед старыми платформами, такими как Express.

мопс

Pug (ранее известный как Jade) — это краткий язык для написания HTML-шаблонов.

  • Производит HTML
  • Поддерживает динамический код
  • Поддерживает повторное использование (СУХОЙ)

Это один из самых популярных шаблонных языков, используемых в Koa.

MongoDB и Mongoose

MongoDB — это база данных документов с открытым исходным кодом, разработанная для простоты разработки и масштабирования. Мы будем использовать эту базу данных для хранения данных.

Mongoose — это клиентский API для node.js, который облегчает доступ к нашей базе данных из нашего приложения Koa.

Koa.js — Окружающая среда

Чтобы начать разработку с использованием инфраструктуры Koa, вам необходимо установить Node и npm (менеджер пакетов узлов). Если у вас их еще нет, перейдите к настройке узла для установки узла в вашей локальной системе. Убедитесь, что узел и npm установлены, выполнив следующие команды в вашем терминале.

$ node --version
$ npm --version

Вы должны получить вывод, похожий на —

v5.0.0
3.5.2

Убедитесь, что версия вашего узла выше 6.5.0. Теперь, когда у нас настроены Node и npm, давайте разберемся, что такое npm и как его использовать.

Диспетчер пакетов узлов (npm)

npm — менеджер пакетов для узла. Реестр npm — это общедоступная коллекция пакетов с открытым исходным кодом для Node.js, интерфейсных веб-приложений, мобильных приложений, роботов, маршрутизаторов и множества других потребностей сообщества JavaScript. npm позволяет нам получить доступ ко всем этим пакетам и установить их локально. Вы можете просмотреть список пакетов, доступных на npm на npmJS .

Как использовать npm?

Существует два способа установки пакета с использованием npm — глобально и локально.

Глобально — этот метод обычно используется для установки инструментов разработки и пакетов на основе CLI. Чтобы установить пакет глобально, используйте следующую команду.

$ npm install -g <package-name>

Локально — этот метод обычно используется для установки фреймворков и библиотек. Локально установленный пакет можно использовать только в том каталоге, в котором он установлен. Чтобы установить пакет локально, используйте ту же команду, что и выше, без флага — g .

$ npm install <package-name>

Всякий раз, когда мы создаем проект с использованием npm, нам нужно предоставить файл package.json, в котором есть все подробности о нашем проекте. npm облегчает нам настройку этого файла. Давайте настроим наш проект развития.

Шаг 1 — Запустите ваш терминал / cmd, создайте новую папку с именем hello-world и перейдите в нее cd —

Окружающая среда МакДир

Шаг 2 — Теперь, чтобы создать файл package.json с помощью npm, используйте следующее.

npm init

Он попросит у вас следующую информацию —

Окружающая среда НПМ

Просто продолжайте нажимать ввод и введите свое имя в поле «имя автора».

Шаг 3 — Теперь у нас есть настроенный файл package.json, мы установим Koa. Чтобы установить Koa и добавить его в наш файл package.json, используйте следующую команду.

$ npm install --save koa

Чтобы подтвердить правильность установки Koa, выполните следующую команду.

$ ls node_modules #(dir node_modules for windows)

Совет — Флаг —save можно заменить на флаг -S . Этот флаг гарантирует, что Koa будет добавлена ​​в качестве зависимости к нашему файлу package.json. Это имеет преимущество: в следующий раз, когда нам нужно будет установить все зависимости нашего проекта, нам просто нужно запустить команду npm install, и она найдет зависимости в этом файле и установит их для нас.

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

$ npm install -g nodemon

Теперь мы все готовы погрузиться в Коа!

Koa.js — Hello World

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

var koa = require('koa');
var app = new koa();

app.use(function* (){
   this.body = 'Hello world!';
});

app.listen(3000, function(){
   console.log('Server running on https://localhost:3000')
});

Сохраните файл, перейдите в свой терминал и введите.

$ nodemon app.js

Это запустит сервер. Чтобы протестировать это приложение, откройте браузер и перейдите по адресу https: // localhost: 3000, и вы должны получить следующее сообщение.

Привет, мир

Как работает это приложение?

Первая строка импортирует Koa в наш файл. У нас есть доступ к его API через переменную Koa. Мы используем его для создания приложения и назначения его в var app.

app.use (function) — эта функция является промежуточным программным обеспечением, которое вызывается всякий раз, когда наш сервер получает запрос. Мы узнаем больше о промежуточном программном обеспечении в следующих главах. Функция обратного вызова является генератором, который мы увидим в следующей главе. Контекст этого генератора называется контекстом в Коа. Этот контекст используется для доступа и изменения объектов запроса и ответа. Мы устанавливаем тело этого ответа как Hello world! ,

app.listen (port, function) — эта функция связывает и прослушивает соединения на указанном порту. Порт является единственным обязательным параметром здесь. Функция обратного вызова выполняется, если приложение работает успешно.

Koa.js — Генераторы

Одна из самых интересных новых функций JavaScript ES6 — это новая функция, называемая генератором. До генераторов весь сценарий обычно использовался для выполнения сверху вниз, без простого способа остановить выполнение кода и возобновить работу с тем же стеком позже. Генераторы — это функции, которые можно завершить, а затем снова ввести. Их контекст (привязки переменных) будет сохранен при повторном входе.

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

var generator_func = function* (){
   yield 1;
   yield 2;
};

var itr = generator_func();
console.log(itr.next());
console.log(itr.next());
console.log(itr.next());

При запуске приведенного выше кода, следующим будет результат.

{ value: 1, done: false }
{ value: 2, done: false }
{ value: undefined, done: true }

Давайте посмотрим внутрь кода выше. Сначала мы создаем генератор под названием generator_func () . Мы создали экземпляр этой странно выглядящей функции и присвоили ее itr . Затем мы начали вызывать next () для этой переменной itr.

Вызов next () запускает генератор и работает до тех пор, пока не достигнет доходности. Затем он возвращает объект со значением и выполнено, где значение имеет значение выражения. Это выражение может быть чем угодно. На этом этапе он приостанавливает выполнение. Опять же, когда мы вызываем эту функцию (далее), генератор возобновляет выполнение с последней точки доходности, причем состояние функции остается неизменным во время паузы, до следующей точки доходности. Это делается до тех пор, пока в коде больше не будет точек доходности.

Генераторы в Коа

Итак, почему мы обсуждаем генераторы в этом уроке. Как вы, наверное, помните из программы hello world, мы использовали нотацию функции * () для передачи обратного вызова в app.use (). Koa — это объект, который содержит массив функций генератора промежуточного программного обеспечения, все из которых составляются и выполняются в виде стека по каждому запросу. Коа также осуществляет нисходящий поток с последующим восходящим потоком управления.

Посмотрите на следующий пример, чтобы понять это лучше.

var koa = require('koa');
var app = koa();
 
app.use(function* (next) {
   //do something before yielding to next generator function 
   
   //in line which will be 1st event in downstream
   console.log("1");
   yield next;
 
   //do something when the execution returns upstream, 
   //this will be last event in upstream
   console.log("2");
});
app.use(function* (next) {
   // This shall be 2nd event downstream
   console.log("3");
   yield next;
 
   // This would be 2nd event upstream
   console.log("4");
});
app.use(function* () { 
   // Here it would be last function downstream
   console.log("5");
   
   // Set response body
   this.body = "Hello Generators";

   // First event of upstream (from the last to first)
   console.log("6");
});

app.listen(3000);

При запуске приведенного выше кода и переходе по адресу https: // localhost: 3000 / мы получаем следующий вывод на нашей консоли.

1
3
5
6
4
2

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

Koa.js — Маршрутизация

Веб-фреймворки предоставляют ресурсы, такие как HTML-страницы, скрипты, изображения и т. Д. По разным маршрутам. Коа не поддерживает маршруты в основном модуле. Нам нужно использовать модуль Koa-router, чтобы легко создавать маршруты в Koa. Установите этот модуль с помощью следующей команды.

npm install --save koa-router

Теперь, когда у нас установлен Koa-роутер, давайте рассмотрим простой пример маршрута GET.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();              //Instantiate the router
_.get('/hello', getMessage);   // Define routes

function *getMessage() {
   this.body = "Hello world!";
};

app.use(_.routes());           //Use the routes defined using the router
app.listen(3000);

Если мы запустим наше приложение и перейдем к localhost: 3000 / hello, сервер получит запрос get по маршруту «/ hello». Наше приложение Koa выполняет функцию обратного вызова, прикрепленную к этому маршруту, и отправляет «Hello World!» как ответ.

Маршрутизация привет

У нас также может быть несколько разных методов на одном и том же маршруте. Например,

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router(); //Instantiate the router

_.get('/hello', getMessage);
_.post('/hello', postMessage);

function *getMessage() {
	this.body = "Hello world!";
};
function *postMessage() {
   this.body = "You just called the post method at '/hello'!\n";
};
app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Чтобы проверить этот запрос, откройте свой терминал и используйте cURL для выполнения следующего запроса.

curl -X POST "https://localhost:3000/hello"

Curl Routing

Express предоставляет специальный метод all для обработки всех типов методов http на определенном маршруте с использованием одной и той же функции. Чтобы использовать этот метод, попробуйте следующее —

_.all('/test', allMessage);

function *allMessage(){
   this.body = "All HTTP calls regardless of the verb will get this response";
};

Koa.js — Создание URL

Теперь мы можем определить маршруты; они либо статичны, либо фиксированы. Чтобы использовать динамические маршруты, нам нужно предоставить разные типы маршрутов. Использование динамических маршрутов позволяет нам передавать параметры и обрабатывать их. Ниже приведен пример динамического маршрута.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/:id', sendID);

function *sendID() {
   this.body = 'The id you specified is ' + this.params.id;
}

app.use(_.routes());
app.listen(3000);

Чтобы проверить это, перейдите на https: // localhost: 3000/123 . Вы получите следующий ответ.

URL Building ID

Вы можете заменить «123» в URL-адресе на что-либо еще, и это будет отражено в ответе. Ниже приведен сложный пример вышесказанного.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/things/:name/:id', sendIdAndName);

function *sendIdAndName(){
   this.body = 'id: ' + this.params.id + ' and name: ' + this.params.name;
};

app.use(_.routes());

app.listen(3000);

Чтобы проверить это, перейдите по адресу https: // localhost: 3000 / things / tutorialspoint / 12345 .

URL Строительный Комплекс

Вы можете использовать объект this.params для доступа ко всем параметрам, которые вы передаете в URL. Обратите внимание, что вышеупомянутые два имеют разные пути. Они никогда не будут пересекаться. Также, если вы хотите выполнить код, когда получите «/ вещи», вам нужно определить его отдельно.

Маршруты, соответствующие шаблону

Вы также можете использовать регулярное выражение для ограничения соответствия параметров URL. Допустим, вам нужен идентификатор, состоящий из пяти цифр. Вы можете использовать следующее определение маршрута.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/things/:id([0-9]{5})', sendID);

function *sendID(){
   this.body = 'id: ' + this.params.id;
}

app.use(_.routes());
app.listen(3000);

Обратите внимание, что это будет соответствовать только запросам, которые имеют 5-значный длинный идентификатор. Вы можете использовать более сложные регулярные выражения для сопоставления / проверки ваших маршрутов. Если ни один из ваших маршрутов не соответствует запросу, вы получите сообщение Не найдено в качестве ответа.

Например, если мы определяем те же маршруты, что и выше, при запросе с действительным URL, мы получаем —

URL-адрес соответствует

Koa.js — методы HTTP

Метод HTTP предоставляется в запросе и определяет операцию, запрошенную клиентом. В следующей таблице приведены наиболее часто используемые методы HTTP.

Sr.No. Метод и описание
1

ПОЛУЧИТЬ

Метод GET запрашивает представление указанного ресурса. Запросы с использованием GET должны только извлекать данные и не должны иметь никакого другого эффекта.

2

СООБЩЕНИЕ

Метод POST запрашивает, чтобы сервер принял данные, включенные в запрос, в качестве нового объекта / объекта ресурса, идентифицированного URI.

3

ПОЛОЖИЛ

Метод PUT запрашивает, чтобы сервер принял данные, включенные в запрос, как модификацию существующего объекта, идентифицированного URI. Если он не существует, метод PUT должен его создать.

4

УДАЛЯТЬ

Метод DELETE запрашивает, чтобы сервер удалил указанный ресурс.

ПОЛУЧИТЬ

Метод GET запрашивает представление указанного ресурса. Запросы с использованием GET должны только извлекать данные и не должны иметь никакого другого эффекта.

СООБЩЕНИЕ

Метод POST запрашивает, чтобы сервер принял данные, включенные в запрос, в качестве нового объекта / объекта ресурса, идентифицированного URI.

ПОЛОЖИЛ

Метод PUT запрашивает, чтобы сервер принял данные, включенные в запрос, как модификацию существующего объекта, идентифицированного URI. Если он не существует, метод PUT должен его создать.

УДАЛЯТЬ

Метод DELETE запрашивает, чтобы сервер удалил указанный ресурс.

Это самые распространенные методы HTTP. Чтобы узнать больше о них, зайдите на https://www.tutorialspoint.com/http/http_methods.htm .

Koa.js — Запрос объекта

Объект Koa Request — это абстракция поверх ванильного объекта запроса узла, предоставляющий дополнительные функциональные возможности, которые полезны для повседневной разработки HTTP-сервера. Объект запроса Koa встроен в объект контекста this . Давайте выйдем из объекта запроса всякий раз, когда мы получим запрос.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/hello', getMessage);

function *getMessage(){
   console.log(this.request);
   this.body = 'Your request has been logged.';
}
app.use(_.routes());
app.listen(3000);

Когда вы запустите этот код и перейдете по адресу https: // localhost: 3000 / hello , вы получите следующий ответ.

Объект запроса

На вашей консоли вы выйдете из объекта запроса.

{ 
   method: 'GET',
   url: '/hello/',
   header: 
   { 
      host: 'localhost:3000',
      connection: 'keep-alive',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) 
         AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
      accept: 'text/html,application/xhtml+xml,
         application/xml;q = 0.9,image/webp,*/*;q = 0.8',
      dnt: '1',
      'accept-encoding': 'gzip, deflate, sdch',
      'accept-language': 'en-US,en;q = 0.8' 
   }
}

У нас есть доступ ко многим полезным свойствам запроса, использующим этот объект. Давайте посмотрим на некоторые примеры.

request.header

Предоставляет все заголовки запроса.

request.method

Предоставляет метод запроса (GET, POST и т. Д.)

request.href

Предоставляет полный URL-адрес запроса.

request.path

Предоставляет путь к запросу. Без строки запроса и базового URL.

request.query

Дает разобранную строку запроса. Например, если мы запишем это по запросу, такому как https: // localhost: 3000 / hello /? Name = Ayush & age = 20 & country = India , мы получим следующий объект.

{
   name: 'Ayush',
   age: '20',
   country: 'India'
}

request.accepts (тип)

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

Вы можете узнать больше об объекте запроса в документации по запросу .

Koa.js — объект ответа

Объект отклика Koa — это абстракция поверх ванильного объекта отклика узла, предоставляющий дополнительную функциональность, полезную для повседневной разработки HTTP-сервера. Объект ответа Koa встроен в объект контекста, this . Давайте выйдем из объекта ответа всякий раз, когда мы получим запрос.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/hello', getMessage);

function *getMessage(){
   this.body = 'Your request has been logged.';
   console.log(this.response);
}

app.use(_.routes());
app.listen(3000);

Когда вы запустите этот код и перейдете по адресу https: // localhost: 3000 / hello, вы получите следующий ответ.

Объект запроса

На вашей консоли вы выйдете из объекта запроса.

{ 
   status: 200,
   message: 'OK',
   header: 
   {
      'content-type': 'text/plain; charset=utf-8',
      'content-length': '12' 
   },
   body: 'Your request has been logged.' 
}

Статус и сообщение автоматически устанавливаются Koa, но могут быть изменены нами. Если мы не устанавливаем тело ответа, код состояния устанавливается равным 404. Как только мы устанавливаем тело ответа, по умолчанию устанавливается статус 200. Мы можем явно переопределить это поведение.

У нас есть доступ ко многим полезным свойствам ответа, использующим этот объект. Давайте посмотрим на некоторые примеры —

response.header

Предоставляет все заголовки ответа.

response.status

Предоставляет статус ответа (200, 404, 500 и т. Д.). Это свойство также используется для установки статуса ответа.

response.message

Предоставляет ответное сообщение. Это свойство также используется для установки пользовательских сообщений с ответами. Это связано с response.status.

response.body

Получить или установить тело ответа. Обычно мы получаем к нему доступ с помощью объекта контекста. Это просто еще один способ получить к нему доступ. Тело может иметь тип: String, Buffer, Stream, Object или Null.

response.type

Получить или установить тип содержимого текущего ответа.

response.get (поле)

Эта функция используется для получения значений заголовков в поле значения без учета регистра.

response.set (поле, значение)

Эта функция используется для установки заголовка ответа с использованием пары поле и значение.

response.remove (поле)

Эта функция используется для сброса заголовка ответа с использованием имени поля.

Вы можете прочитать больше об объекте ответа в документации на Response .

Koa.js — Перенаправления

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

Давайте создадим страницу с ошибкой и перенаправим на эту страницу всякий раз, когда кто-то запрашивает неверно сформированный URL.

var koa = require('koa');
var router = require('koa-router');
var app = koa();
var _ = router();

_.get('/not_found', printErrorMessage);
_.get('/hello', printHelloMessage);

app.use(_.routes());
app.use(handle404Errors);

function *printErrorMessage() {
   this.status = 404;
   this.body = "Sorry we do not have this resource.";
}
function *printHelloMessage() {
   this.status = 200;
   this.body = "Hey there!";
}
function *handle404Errors(next) {
   if (404 != this.status) return;
   this.redirect('/not_found');
}
app.listen(3000);

Когда мы запустим этот код и перейдем к любому маршруту, отличному от / hello, мы будем перенаправлены на / not_found. Мы поместили промежуточное ПО в конец (вызов функции app.use для этого промежуточного ПО). Это гарантирует, что мы наконец достигнем промежуточного программного обеспечения и отправим соответствующий ответ. Ниже приведены результаты, которые мы видим, когда запускаем приведенный выше код.

Когда мы перейдем к https: // localhost: 3000 / hello , мы получим —

Переадресация Привет

Если мы перейдем к любому другому маршруту, мы получим —

Ошибка перенаправления

Koa.js — Обработка ошибок

Обработка ошибок играет важную роль в создании веб-приложений. Коа также использует промежуточное программное обеспечение для этой цели.

В Koa вы добавляете промежуточное программное обеспечение, которое пытается {yield next} как одно из первых промежуточных программ. Если мы встречаем какую-либо ошибку в нисходящем направлении, мы возвращаемся к соответствующему предложению catch и обрабатываем здесь ошибку. Например —

var koa = require('koa');
var app = koa();

//Error handling middleware
app.use(function *(next) {
   try {
      yield next;
   } catch (err) {
      this.status = err.status || 500;
      this.body = err.message;
      this.app.emit('error', err, this);
   }
});

//Create an error in the next middleware
//Set the error message and status code and throw it using context object

app.use(function *(next) {
   //This will set status and message
   this.throw('Error Message', 500);
});

app.listen(3000);

Мы намеренно создали ошибку в приведенном выше коде и обрабатываем ее в блоке catch нашего первого промежуточного программного обеспечения. Затем он отправляется на нашу консоль, а также отправляется в качестве ответа нашему клиенту. Ниже приведено сообщение об ошибке, которое мы получаем, когда запускаем эту ошибку.

InternalServerError: Error Message
   at Object.module.exports.throw 
      (/home/ayushgp/learning/koa.js/node_modules/koa/lib/context.js:91:23)
   at Object.<anonymous> (/home/ayushgp/learning/koa.js/error.js:18:13)
   at next (native)
   at onFulfilled (/home/ayushgp/learning/koa.js/node_modules/co/index.js:65:19)
   at /home/ayushgp/learning/koa.js/node_modules/co/index.js:54:5
   at Object.co (/home/ayushgp/learning/koa.js/node_modules/co/index.js:50:10)
   at Object.toPromise (/home/ayushgp/learning/koa.js/node_modules/co/index.js:118:63)
   at next (/home/ayushgp/learning/koa.js/node_modules/co/index.js:99:29)
   at onFulfilled (/home/ayushgp/learning/koa.js/node_modules/co/index.js:69:7)
   at /home/ayushgp/learning/koa.js/node_modules/co/index.js:54:5

Прямо сейчас любой запрос, отправленный на сервер, приведет к этой ошибке.

Koa.js — каскадный

Функции промежуточного программного обеспечения — это функции, которые имеют доступ к объекту контекста и следующей функции промежуточного программного обеспечения в цикле запроса-ответа приложения. Эти функции используются для изменения объектов запроса и ответа для таких задач, как синтаксический анализ тела запроса, добавление заголовков ответа и т. Д. Коа идет дальше, уступая «downstream» , а затем возвращает управление обратно «upstream» . Этот эффект называется каскадным .

Ниже приведен простой пример функции промежуточного программного обеспечения в действии.

var koa = require('koa');
var app = koa();
var _ = router();

//Simple request time logger
app.use(function* (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.
   yield next;
});

app.listen(3000);

Вышеуказанное промежуточное программное обеспечение вызывается для каждого запроса на сервере. Таким образом, после каждого запроса мы получим следующее сообщение в консоли.

A new request received at 1467267512545

Чтобы ограничить его конкретным маршрутом (и всеми его подчиненными маршрутами), нам просто нужно создать маршруты, как мы это делали для маршрутизации. На самом деле это промежуточное программное обеспечение только для обработки нашего запроса.

Например,

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

//Simple request time logger
_.get('/request/*', function* (next) {
   console.log("A new request received at " + Date.now());
   yield next;
});

app.use(_.routes());
app.listen(3000);

Теперь всякий раз, когда вы запрашиваете какой-либо подкаталог / request, только тогда он будет записывать время.

Заказ звонков промежуточного программного обеспечения

Одна из самых важных вещей в промежуточном программном обеспечении в Koa состоит в том, что порядок, в котором они записаны / включены в ваш файл, — это порядок, в котором они выполняются в нисходящем направлении. Как только мы достигаем оператора выхода промежуточного программного обеспечения, он переключается на следующее промежуточное программное обеспечение в очереди, пока мы не достигнем последнего. Затем мы снова начинаем движение вверх и возобновляем функции из операторов yield.

Например, в следующем фрагменте кода первая функция выполняется сначала до yield, затем второе промежуточное программное обеспечение до yield, затем третья. Поскольку у нас больше нет промежуточного программного обеспечения, мы начинаем двигаться обратно вверх, выполняя в обратном порядке, т. Е. Третий, второй, первый. Этот пример суммирует, как использовать промежуточное ПО способом Koa.

var koa = require('koa');
var app = koa();

//Order of middlewares
app.use(first);
app.use(second);
app.use(third);

function *first(next) {
   console.log("I'll be logged first. ");
   
   //Now we yield to the next middleware
   yield next;
   
   //We'll come back here at the end after all other middlewares have ended
   console.log("I'll be logged last. ");
};

function *second(next) {
   console.log("I'll be logged second. ");
   yield next;
   console.log("I'll be logged fifth. ");
};

function *third(next) {
   console.log("I'll be logged third. ");
   yield next;
   console.log("I'll be logged fourth. ");
};

app.listen(3000);

Когда мы запустим «/» после запуска этого кода, на нашей консоли мы получим —

I'll be logged first. 
I'll be logged second. 
I'll be logged third. 
I'll be logged fourth. 
I'll be logged fifth. 
I'll be logged last. 

Следующая диаграмма обобщает то, что на самом деле происходит в приведенном выше примере.

Middleware Desc

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

Стороннее промежуточное программное обеспечение

Список стороннего промежуточного программного обеспечения для экспресса доступен здесь. Ниже приведены некоторые из наиболее часто используемых промежуточных программ —

  • КоА-bodyparser
  • КоА-маршрутизатор
  • КоА-статические
  • КоА-компресс

Мы обсудим несколько промежуточных программ в следующих главах.

Koa.js — шаблоны

Мопс — движок шаблонов. Движки шаблонов используются для устранения загромождения кода нашего сервера с помощью HTML, дико объединяя строки с существующими шаблонами HTML. Мопс — очень мощный движок шаблонов, который имеет множество функций, таких как фильтры, включает в себя, наследование, интерполяция и т. Д. Есть много оснований, чтобы покрыть это.

Чтобы использовать Pug с Koa, нам нужно установить его с помощью следующей команды.

$ npm install --save pug koa-pug

Как только pug установлен, установите его в качестве движка шаблонов для вашего приложения. Добавьте следующий код в файл app.js.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

var _ = router(); //Instantiate the router

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Теперь создайте новый каталог с именем views. Внутри каталога создайте файл с именем first_view.pug и введите в него следующие данные.

doctype html
html
   head
      title = "Hello Pug"
   body
      p.greetings#people Hello Views!

Чтобы запустить эту страницу, добавьте следующий маршрут в ваше приложение.

_.get('/hello', getMessage); // Define routes

function *getMessage(){
   this.render('first_view');
};

Вы получите вывод как —

Привет Просмотров

Pug конвертирует эту очень простую на вид разметку в html. Нам не нужно отслеживать закрытие наших тегов, не нужно использовать ключевые слова class и id, лучше использовать ‘.’ и «#», чтобы определить их. Приведенный выше код сначала преобразуется в

<!DOCTYPE html>
<html>
   <head>
      <title>Hello Pug</title>
   </head>
    
   <body>
      <p class = "greetings" id = "people">Hello Views!</p>
   </body>
</html>

Мопс способен на гораздо большее, чем просто упрощение разметки HTML. Давайте рассмотрим некоторые из этих особенностей мопса.

Простые теги

Теги вложены в соответствии с их отступом. Как и в приведенном выше примере, тег <title> был вставлен в тег <head> , поэтому он был внутри него. Тем не менее, тег <body> был на том же отступе, поэтому он был родственным тегом <head> .

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

Есть три способа поместить текст внутри тега —

  • Пространство отделено —
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 koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app // equals to pug.use(app) and app.use(pug.middleware)
});

var _ = router(); //Instantiate the router

_.get('//dynamic_view', dynamicMessage); // Define routes

function *dynamicMessage(){
   this.render('dynamic', {
      name: "TutorialsPoint", 
      url:"https://www.tutorialspoint.com"
   });
};

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Затем создайте новый файл представления в каталоге представлений с именем dynamic.pug, используя следующий код.

html
   head
      title = name
   body
      h1 = name
      a(href = url) URL

Откройте localhost: 3000 / dynamic в вашем браузере, и следующий должен быть вывод.

Шаблонные Переменные

Мы также можем использовать эти переданные переменные в тексте. Чтобы вставить переданные переменные в текст тега, мы используем синтаксис # {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

Когда мы рендерим это, используя наши маршруты, и если мы передаем объект вроде —

this.render('/dynamic',{user: 
   {name: "Ayush", age: "20"}
});

Появится сообщение «Привет, Аюш». Однако, если мы не передадим какой-либо объект или не передадим объект без ключа пользователя, мы получим ссылку «Зарегистрироваться».

Включить и компоненты

Мопс обеспечивает очень интуитивно понятный способ создания компонентов для веб-страницы. Например, если вы видите новостной сайт, заголовок с логотипом и категориями всегда фиксируется. Вместо того, чтобы копировать это в каждое представление, мы можем использовать include. Следующий пример показывает, как мы можем использовать include —

Создайте три представления с помощью следующего кода —

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 koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

var _ = router(); //Instantiate the router

_.get('/components', getComponents);

function *getComponents(){
   this.render('content.pug');
}

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Перейдите на localhost: 3000 / components , вы должны получить следующий вывод.

Компоненты шаблонов

include также может использоваться для включения открытого текста, CSS и JavaScript.

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

Koa.js — данные формы

Формы являются неотъемлемой частью Интернета. Почти каждый веб-сайт, который мы посещаем, предлагает нам формы, которые отправляют или получают некоторую информацию для нас. Чтобы начать работу с формами, мы сначала установим koa-body. Чтобы установить это, перейдите в свой терминал и используйте —

$ npm install --save koa-body

Замените содержимое файла app.js следующим кодом.

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');
var app = koa();

//Set up Pug
var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},
   multipart: true,
   urlencoded: true
}));

_.get('/', renderForm);
_.post('/', handleForm);

function * renderForm(){
   this.render('form');
}
function *handleForm(){
   console.log(this.request.body);
   console.log(this.req.body);
   this.body = this.request.body; //This is where the parsed request is stored
}

app.use(_.routes()); 
app.listen(3000);

Новые вещи, которые мы делаем здесь, это импорт анализатора тела и multer. Мы используем анализатор тела для парсинга запросов заголовков json и x-www-form-urlencoded, в то время как для анализа multipart / form-data мы используем multer.

Давайте создадим HTML-форму, чтобы проверить это! Создайте новый вид с именем form.pug со следующим кодом.

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 = "Koa form")
         br
         button(type = "submit") Send my greetings

Запустите свой сервер, используя —

nodemon index.js

Теперь перейдите на localhost: 3000 / и заполните форму, как вам нравится, и отправьте ее. Вы получите ответ как —

Форма получена

Посмотрите на консоль, она покажет тело вашего запроса в виде объекта JavaScript. Например —

Форма консоли

Объект this.request.body содержит ваше проанализированное тело запроса. Чтобы использовать поля из этого объекта, просто используйте их как обычные объекты JS.

Это всего лишь один из способов отправить запрос. Есть много других способов, но они не имеют отношения к этому, потому что наше приложение Koa будет обрабатывать все эти запросы одинаково. Чтобы узнать больше о различных способах подачи запроса, загляните на эту страницу.

Koa.js — Загрузка файлов

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

Мы уже использовали промежуточное программное обеспечение koa-body для разбора запросов. Это промежуточное ПО также используется для загрузки файлов. Давайте создадим форму, которая позволит нам загружать файлы, а затем сохранять эти файлы с помощью Koa. Сначала создайте шаблон с именем file_upload.pug со следующим содержимым.

html
   head
      title File uploads
   body
      form(action = "/upload" method = "POST" enctype = "multipart/form-data")
         div
            input(type = "text" name = "name" placeholder = "Name")
         
         div
            input(type = "file" name = "image")
         
         div
            input(type = "submit")

Обратите внимание, что вам нужно указать тот же тип кодировки, что и выше в вашей форме. Теперь давайте обработаем эти данные на нашем сервере.

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');
var app = koa();

//Set up Pug
var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app 
});

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},    //This is where the files would come
   multipart: true,
   urlencoded: true
}));

var _ = router(); //Instantiate the router

_.get('/files', renderForm);
_.post('/upload', handleForm);

function * renderForm(){
   this.render('file_upload');
}

function *handleForm(){
   console.log("Files: ", this.request.body.files);
   console.log("Fields: ", this.request.body.fields);
   this.body = "Received your data!"; //This is where the parsed request is stored
}

app.use(_.routes()); 
app.listen(3000);

Когда вы запустите это, вы получите следующую форму.

Форма загрузки файла

Когда вы отправите это, ваша консоль выдаст следующий вывод.

Экран файловой консоли

Загруженные файлы хранятся в пути в вышеприведенном выводе. Вы можете получить доступ к файлам в запросе, используя this.request.body.files, и к полям в этом запросе this.request.body.fields .

Koa.js — Статические файлы

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

Нам нужно промежуточное программное обеспечение для этой цели. Идите вперед и установите коа-служить

$ npm install --save koa-static

Теперь нам нужно использовать это промежуточное ПО. Перед этим создайте каталог с именем public. Мы будем хранить все наши статические файлы здесь. Это позволяет нам обеспечивать безопасность нашего серверного кода, так как ничто над этой общей папкой не будет доступно для клиентов. После того, как вы создали публичный каталог, создайте в нем файл с именем hello.txt с любым контентом, который вам нравится. Теперь добавьте следующее в ваш app.js.

var serve = require('koa-static');
var koa = require('koa');
var app = koa();

app.use(serve('./public'));

app.listen(3000);

Примечание. Koa ищет файлы относительно статического каталога, поэтому имя статического каталога не является частью URL. Корневой маршрут теперь установлен для вашего публичного каталога, поэтому все загружаемые вами статические файлы будут считаться публичными в качестве корневого. Чтобы проверить, что это работает нормально, запустите свое приложение и посетите https: // localhost: 3000 / hello.txt

Вы должны получить следующий вывод. Обратите внимание, что это не документ HTML или представление Pug, а простой текстовый файл.

Статические файлы

Несколько статических Dirs

Мы также можем установить несколько статических каталогов активов, используя —

var serve = require('koa-static');
var koa = require('koa');
var app = koa();

app.use(serve('./public'));
app.use(serve('./images'));

app.listen(3000);

Теперь, когда мы запрашиваем файл, Koa будет искать эти каталоги и отправлять нам соответствующий файл.

Koa.js — Печенье

Файлы cookie — это простые небольшие файлы / данные, которые отправляются клиенту по запросу сервера и хранятся на стороне клиента. Каждый раз, когда пользователь загружает сайт обратно, этот файл cookie отправляется вместе с запросом. Это помогает отслеживать действия пользователей. Существует множество способов использования файлов cookie HTTP.

  • Управление сессиями
  • Персонализация (системы рекомендаций)
  • Отслеживание пользователей

Чтобы использовать куки с Koa, у нас есть функции: ctx.cookies.set () и ctx.cookies.get () . Чтобы установить новый файл cookie, давайте определим новый маршрут в нашем приложении Koa.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie() {
   this.cookie.set('foo', 'bar', {httpOnly: false});
}

var _ = router();

app.use(_.routes());
app.listen(3000);

Чтобы проверить, установлен ли файл cookie, просто перейдите в браузер, запустите консоль и введите —

console.log(document.cookie);

Это приведет к следующему выводу (возможно, у вас установлено больше файлов cookie, возможно, из-за расширений в вашем браузере).

"foo = bar"

Вот пример вышесказанного.

печенье

Браузер также отправляет файлы cookie каждый раз, когда запрашивает сервер. Чтобы просмотреть файл cookie на своем сервере, на консоли сервера в маршруте добавьте следующий код к этому маршруту.

console.log('Cookies: foo = ', this.cookies.get('foo'));

В следующий раз, когда вы отправите запрос по этому маршруту, вы получите следующий вывод.

Cookies: foo = bar

Добавление файлов cookie со сроком действия

Вы можете добавить куки, срок действия которых истекает. Чтобы добавить cookie, срок действия которого истекает, просто передайте объект со свойством expires, установленным на время, когда вы хотите, чтобы срок его действия истек. Например,

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie(){
   //Expires after 360000 ms from the time it is set.
	this.cookies.set('name', 'value', { 
      httpOnly: false, expires: 360000 + Date.now() });
}

var _ = router();

app.use(_.routes());
app.listen(3000);

Удаление существующих файлов cookie

Чтобы удалить cookie, просто установите cookie в пустую строку. Например, если вам нужно очистить файл cookie с именем foo , используйте следующий код.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie(){
   //Expires after 360000 ms from the time it is set.
   this.cookies.set('name', '');
}

var _ = router();

app.use(_.routes());
app.listen(3000);

Это приведет к сбросу указанного куки. Обратите внимание, что вы должны оставить параметр HttpOnly равным true, если не используете cookie в коде на стороне клиента.

Koa.js — Сессии

HTTP не имеет состояния, поэтому, чтобы связать запрос с любым другим запросом, вам нужен способ хранения пользовательских данных между HTTP-запросами. Файлы cookie и параметры URL являются подходящими способами передачи данных между клиентом и сервером. Тем не менее, они оба читаемы на стороне клиента. Сессии решают именно эту проблему. Вы назначаете клиенту идентификатор, и он делает все дальнейшие запросы, используя этот идентификатор. Информация, связанная с клиентом, хранится на сервере, связанном с этим идентификатором.

Нам понадобится koa-сессия, поэтому установите его, используя —

npm install --save koa-session

Мы установим промежуточное программное обеспечение для коа-сессии . В этом примере мы будем использовать оперативную память для хранения сессий. Никогда не используйте это в производственных условиях. Промежуточное программное обеспечение сеанса обрабатывает все, то есть создает сеанс, устанавливает cookie сеанса и создает объект сеанса в объекте контекста.

Всякий раз, когда мы делаем запрос от того же клиента снова, мы будем хранить информацию об их сеансе у нас (учитывая, что сервер не был перезапущен). Мы можем добавить больше свойств к этому объекту сеанса. В следующем примере мы создадим счетчик просмотров для клиента.

var session = require('koa-session');
var koa = require('koa');
var app = koa();

app.keys = ['Shh, its a secret!'];
app.use(session(app));  // Include the session middleware

app.use(function *(){
   var n = this.session.views || 0;
   this.session.views = ++n;
   
   if(n === 1)
      this.body = 'Welcome here for the first time!';
   else
      this.body = "You've visited this page " + n + " times!";
})

app.listen(3000);

Приведенный выше код делает, когда пользователь посещает сайт, он создает новый сеанс для пользователя и назначает cookie. В следующий раз, когда пользователь заходит, cookie проверяется, и переменная сеанса page_view соответствующим образом обновляется.

Теперь, если вы запустите приложение и перейдете на localhost: 3000, вы получите следующий ответ.

Первая сессия

Если вы вернетесь на страницу, счетчик страниц увеличится. В этом случае страница обновлялась 12 раз.

Сессия 12

Koa.js — Аутентификация

Аутентификация — это процесс, в котором предоставленные учетные данные сравниваются с данными в файле в базе данных авторизованных пользователей в локальной операционной системе или на сервере аутентификации. Если учетные данные совпадают, процесс завершается, и пользователю предоставляется авторизация для доступа.

Мы создадим очень простую систему аутентификации, которая будет использовать базовую аутентификацию HTTP . Это самый простой способ обеспечить контроль доступа, поскольку он не требует файлов cookie, сеансов или чего-либо еще. Чтобы использовать это, клиент должен отправить заголовок авторизации вместе с каждым запросом, который он делает. Имя пользователя и пароль не шифруются, а объединяются в одну строку, как показано ниже.

username:password

Эта строка кодируется с помощью Base64, и перед этим значением ставится слово Basic. Например, если ваше имя пользователя Ayush и пароль India, строка «Ayush: India» будет отправлена ​​в виде закодированного в заголовке авторизации.

Authorization: Basic QXl1c2g6SW5kaWE=

Для реализации этого в вашем приложении koa вам понадобится промежуточное программное обеспечение koa-basic-auth. Установите его, используя —

$ npm install --save koa-basic-auth

Теперь откройте файл app.js и введите в него следующий код.

//This is what the authentication would be checked against
var credentials = { name: 'Ayush', pass: 'India' }

var koa = require('koa');
var auth = require('koa-basic-auth');
var _ = require('koa-router')();

var app = koa();

//Error handling middleware
app.use(function *(next){
   try {
      yield next;
   } catch (err) {
      if (401 == err.status) {
         this.status = 401;
         this.set('WWW-Authenticate', 'Basic');
         this.body = 'You have no access here';
      } else {
         throw err;
      }
   }
});

// Set up authentication here as first middleware. 
// This returns an error if user is not authenticated.
_.get('/protected', auth(credentials), function *(){
   this.body = 'You have access to the protected area.';
   yield next;
});

// No authentication middleware present here.
_.get('/unprotected', function*(next){
   this.body = "Anyone can access this area";
   yield next;
});

app.use(_.routes());
app.listen(3000);

Мы создали промежуточное программное обеспечение для обработки ошибок для обработки всех ошибок, связанных с аутентификацией. Затем мы создали 2 маршрута —

  • / protected — доступ к этому маршруту возможен только в том случае, если пользователь отправляет правильный заголовок аутентификации. Для всех остальных это даст ошибку.

  • / unprotected — доступ к этому маршруту может получить любой, с аутентификацией или без нее.

/ protected — доступ к этому маршруту возможен только в том случае, если пользователь отправляет правильный заголовок аутентификации. Для всех остальных это даст ошибку.

/ unprotected — доступ к этому маршруту может получить любой, с аутентификацией или без нее.

Теперь, если вы отправите запрос в / protected без заголовка аутентификации или с неправильными учетными данными, вы получите ошибку. Например,

$ curl https://localhost:3000/protected

Вы получите ответ как —

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic
Content-Type: text/plain; charset=utf-8
Content-Length: 28
Date: Sat, 17 Sep 2016 19:05:56 GMT
Connection: keep-alive

Please authenticate yourself

Однако с правильными учетными данными вы получите ожидаемый ответ. Например,

$ curl -H "Authorization: basic QXl1c2g6SW5kaWE=" https://localhost:3000/protected -i

Вы получите ответ как —

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Sat, 17 Sep 2016 19:07:33 GMT
Connection: keep-alive

You have access to the protected area.

/ Незащищенный маршрут по-прежнему доступен для всех.

Koa.js — Сжатие

Сжатие — это простой и эффективный способ сэкономить трафик и ускорить работу вашего сайта. Он совместим только с современными браузерами и должен использоваться с осторожностью, если ваши пользователи также используют устаревшие браузеры.

При отправке ответов с сервера, если используется сжатие, это может значительно сократить время загрузки. Мы будем использовать промежуточное ПО под названием koa-compress, чтобы заботиться о сжатии файлов, а также устанавливать соответствующие заголовки.

Идите вперед и установите промежуточное программное обеспечение, используя —

$ npm install --save koa-compress

Теперь в вашем файле app.js добавьте следующий код —

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

app.use(compress({
   filter: function (content_type) {
      return /text/i.test(content_type)
   },
   threshold: 2048,
   flush: require('zlib').Z_SYNC_FLUSH
}));

var _ = router(); //Instantiate the router

_.get('/', getRoot);

function *getRoot(next){
   this.render('index');
}

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

Это ставит наше промежуточное программное обеспечение для сжатия на место. Опция фильтра — это функция, которая проверяет тип содержимого ответа, чтобы решить, следует ли сжимать. Параметр порога — это минимальный размер ответа в байтах для сжатия. Это гарантирует, что мы не сжимаем каждый маленький ответ.

Ниже приводится ответ без сжатия.

несжатого

Ниже приведен аналогичный ответ со сжатием.

Сжатый

Если вы посмотрите на вкладку размера внизу, вы можете очень хорошо увидеть разницу между ними. Улучшение более чем на 150%, когда мы сжимаем файлы.

Koa.js — Кэширование

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

Ниже приведены некоторые преимущества включения кэширования в ваши веб-приложения.

  • Стоимость вашей сети уменьшается. Если ваш контент кэшируется, вам нужно будет отправлять меньше его для каждого последующего запроса.

  • Скорость и производительность вашего сайта увеличивается.

  • Ваш контент может быть доступен, даже если ваш клиент не в сети.

Стоимость вашей сети уменьшается. Если ваш контент кэшируется, вам нужно будет отправлять меньше его для каждого последующего запроса.

Скорость и производительность вашего сайта увеличивается.

Ваш контент может быть доступен, даже если ваш клиент не в сети.

Мы будем использовать промежуточное ПО koa-static-cache для реализации кэширования в нашем приложении. Установите это промежуточное ПО, используя —

$ npm install --save koa-static-cache

Перейдите к файлу app.js и добавьте в него следующий код.

var koa = require('koa');
var app = koa();

var path = require('path');
var staticCache = require('koa-static-cache');

app.use(staticCache(path.join(__dirname, 'public'), {
   maxAge: 365 * 24 * 60 * 60  //Add these files to caches for a year
}))

app.listen(3000);

Промежуточное программное обеспечение koa-static-cache используется для кэширования ответов сервера на стороне клиента. Заголовок контроля кэша устанавливается в соответствии с параметрами, которые мы предоставляем при инициализации объекта кэша. Мы установили срок действия этого кэшированного ответа в 1 год. Ниже приводится сравнение запроса, который мы отправили до и после того, как файл был кэширован.

До того, как этот файл был кэширован, возвращенный код состояния был 200, что нормально. Заголовки ответов содержали многократную информацию о содержимом, которое должно быть кэшировано, а также дали ETag для содержимого.

Перед кэшем

В следующий раз, когда запрос был отправлен, он был отправлен вместе с ETtag. Поскольку наш контент на сервере не изменился, соответствующий ему ETag также остался прежним, и клиенту сказали, что локально имеющаяся копия соответствует тому, что предоставит сервер, и должна использовать локальную копию вместо запроса снова.

После кэша

Примечание. Для аннулирования любого кэшированного файла вам просто нужно изменить его имя и обновить ссылку. Это обеспечит наличие нового файла для отправки клиенту, и клиент не сможет загрузить его обратно из кэша.

Koa.js — База данных

Мы получаем запросы, но нигде не храним их. Нам нужна база данных для хранения данных. Мы будем использовать известную базу данных NoSQL под названием MongoDB . Чтобы установить и прочитать о Mongo, перейдите по этой ссылке.

Чтобы использовать Mongo с Koa, нам нужен клиентский API для узла. У нас есть несколько вариантов, однако в этом уроке мы остановимся на мангусте . Mongoose используется для моделирования документов в Node для MongoDB. Моделирование документов означает, что мы создадим модель (во многом как класс в документно-ориентированном программировании), а затем создадим документы, используя эту модель (как мы создаем документы класса в ООП). Вся наша обработка будет производиться на этих «документах», затем, наконец, мы запишем эти документы в нашу базу данных.

Настройка мангуста

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

$ npm install --save mongoose

Прежде чем мы начнем использовать mongoose, мы должны создать базу данных, используя оболочку Mongo. Чтобы создать новую базу данных, откройте свой терминал и введите «Монго». Запустится оболочка Монго, введите следующее.

use my_db

Новая база данных будет создана для вас. Всякий раз, когда вы открываете оболочку Mongo, она по умолчанию будет «тестировать» БД, и вам придется перейти в базу данных, используя ту же команду, что и выше.

Чтобы использовать mongoose, нам потребуется это в нашем файле app.js, а затем подключиться к сервису mongod, работающему на mongodb: // localhost

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

app.use(_.routes());
app.listen(3000);

Теперь наше приложение подключено к нашей базе данных, давайте создадим новую модель. Эта модель будет выступать в качестве коллекции в нашей базе данных. Чтобы создать новую модель, используйте следующий код, прежде чем определять любые маршруты.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

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.use(_.routes());
app.listen(3000);

Приведенный выше код определяет схему для человека и используется для создания мангуста Model Person .

Сохранение документов

Теперь мы создадим новую 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, чтобы отобразить этот документ.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

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);

_.get('/person', getPerson);

function *getPerson(next){
   this.render('person');
   yield next;
}

app.use(_.routes());
app.listen(3000);

Перейдите на localhost: 3000 / чел., Чтобы проверить, правильно ли отображается наша форма. Обратите внимание, что это просто пользовательский интерфейс, он еще не работает. Вот так выглядит наша форма.

Мангуст Создать

Теперь мы определим обработчик почтового маршрута в / person, который будет обрабатывать этот запрос.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

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);

_.post('/person', createPerson);

function *createPerson(next){
   var self = this;
   var personInfo = self.request.body; //Get the parsed information
   
   if(!personInfo.name || !personInfo.age || !personInfo.nationality){
      self.render(
         'show_message', {message: "Sorry, you provided wrong info", type: "error"});
   } else {
      var newPerson = new Person({
         name: personInfo.name,
         age: personInfo.age,
         nationality: personInfo.nationality
      });
      yield newPerson.save(function(err, res) {
         if(err)
            self.render('show_message', 
               {message: "Database error", type: "error"});
         else
            self.render('show_message', 
               {message: "New person added", type: "success", person: personInfo});
      });
   }
}

app.use(_.routes());
app.listen(3000);

В приведенном выше коде, если мы получим любое пустое поле или не получим никакого поля, мы отправим ответ об ошибке. Однако, если мы получаем правильно сформированный документ, мы создаем документ newPerson из модели Person и сохраняем его в нашей БД с помощью функции newPerson.save () . Это определено в mongoose и принимает обратный вызов в качестве аргумента. Этот обратный вызов имеет два аргумента, ошибку и ответ . Это отобразит представление 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);
});

При этом будут получены все документы, для которых поле имеет имя «Аюш» и его возраст равен 20.

Person.find({name: "Ayush", age: 20}, 
   function(err, response){
      console.log(response);
   });

Мы также можем предоставить необходимую нам проекцию, то есть поля, которые нам нужны. Например, если нам нужны только имена людей, национальность которых «индус» , мы используем —

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 koa = require('koa');
var _ = require('koa-router')();
var app = koa();

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);

_.get('/people', getPeople);
function *getPeople(next){
   var self = this;
   
   yield Person.find(function(err, response){
      self.body = response;
   });
}
app.use(_.routes());
app.listen(3000);

Обновление документов

Mongoose предоставляет три функции для обновления документов.

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 koa = require('koa');
var _ = require('koa-router')();
var app = koa();
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);

_.put('/people/:id', updatePerson);

function *updatePerson() {
   var self = this;
   yield Person.findByIdAndUpdate(self.params.id, 
      {$set: {self.request.body}}, function(err, response){
      
      if(err) {
         self.body = {
            message: "Error in updating person with id " + self.params.id};
      } else {
         self.body = response;
      }
   });
}

app.use(_.routes());
app.listen(3000);

Чтобы проверить этот маршрут, введите в своем терминале следующее (замените идентификатор на идентификатор из созданных вами людей).

curl -X PUT --data "name = James&age = 20&nationality = American" https://localhost:3000/people/507f1f77bcf86cd799439011

Это обновит документ, связанный с идентификатором, указанным в маршруте, с указанными выше деталями.

Удаление документов

Мы рассмотрели C reate, R ead и U pdate, теперь мы увидим, как mongoose может использоваться для удаления документов. Здесь есть три функции, в точности как обновление.

Model.remove (условие, [обратный вызов])

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

Person.remove({age:20});

Model.findOneAndRemove (условие, [обратный вызов])

Эта функция удаляет один , наиболее релевантный документ в соответствии с объектом условий. Например,

Person.findOneAndRemove({name: "Ayush"});

Model.findByIdAndRemove (id, [callback])

Эта функция удаляет один документ, идентифицируемый по его идентификатору. Например,

Person.findByIdAndRemove("507f1f77bcf86cd799439011");

Теперь давайте создадим маршрут для удаления людей из нашей базы данных.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

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);

_.delete('/people/:id', deletePerson);
function *deletePerson(next){
   var self = this;
   yield Person.findByIdAndRemove(self.params.id, function(err, response){
      if(err) {
         self.body = {message: "Error in deleting record id " + self.params.id};
      } else {
         self.body = {message: "Person with id " + self.params.id + " removed."};
      }
   });
}

app.use(_.routes());
app.listen(3000);

Чтобы проверить это, используйте следующую команду curl —

curl -X DELETE https://localhost:3000/people/507f1f77bcf86cd799439011

Это удалит человека с данным идентификатором, создающего следующее сообщение.

{message: "Person with id 507f1f77bcf86cd799439011 removed."}

Это завершает, как мы можем создавать простые приложения CRUD, используя MongoDB, mongoose и Koa. Чтобы узнать больше о мангусте, прочитайте документацию по API.

Koa.js — RESTful API

Для создания мобильных приложений, одностраничных приложений, использования вызовов AJAX и предоставления данных клиентам вам потребуется API. Популярный архитектурный стиль структурирования и именования этих API-интерфейсов и конечных точек называется REST (репрезентативное состояние передачи) . HTTP 1.1 был разработан с учетом принципов REST. REST был представлен Роем ​​Филдингом в 2000 году в своей статье Fielding Dissertations.

RESTful URI и методы предоставляют нам практически всю информацию, необходимую для обработки запроса. В следующей таблице приведены способы использования различных глаголов и имена URI. Мы будем создавать API фильмов к концу, поэтому давайте обсудим, как это будет структурировано.

метод URI подробности функция
ПОЛУЧИТЬ /фильмы Безопасный, кэшируемый Получает список всех фильмов и их детали
ПОЛУЧИТЬ / Фильмы / 1234 Безопасный, кэшируемый Получает подробную информацию о фильме id 1234
СООБЩЕНИЕ /фильмы N / A Создает новый фильм с подробной информацией. Ответ содержит URI для этого вновь созданного ресурса.
ПОЛОЖИЛ / Фильмы / 1234 идемпотент Изменяет идентификатор фильма 1234 (создает его, если он еще не существует). Ответ содержит URI для этого вновь созданного ресурса.
УДАЛЯТЬ / Фильмы / 1234 идемпотент Идентификатор фильма 1234 следует удалить, если он существует. Ответ должен содержать статус запроса.
УДАЛИТЬ или ПОСТАВИТЬ /фильмы Недействительным Должен быть недействительным. DELETE и PUT должны указывать, над каким ресурсом они работают.

Теперь давайте создадим этот API в Koa. Мы будем использовать JSON в качестве нашего транспортного формата данных, так как с ним легко работать в JavaScript и у него есть масса других преимуществ. Замените ваш файл index.js следующим:

index.js

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');

var app = koa();

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},
   multipart: true,
   urlencoded: true
}));

//Require the Router we defined in movies.js
var movies = require('./movies.js');

//Use the Router on the sub route /movies
app.use(movies.routes());

app.listen(3000);

Теперь, когда мы настроили наше приложение, давайте сосредоточимся на создании API. Сначала настройте файл movies.js. Мы не используем базу данных для хранения фильмов, но храним их в памяти, поэтому каждый раз, когда сервер перезапускает, добавленные нами фильмы исчезают. Это можно легко имитировать с помощью базы данных или файла (с помощью модуля node fs).

Импортируйте koa-router, создайте Router и экспортируйте его, используя module.exports.

var Router = require('koa-router');
var router = Router({
  prefix: '/movies'
});  //Prefixed all routes with /movies

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('/', sendMovies);
function *sendMovies(next){
   this.body = movies;
   yield next;
}

Вот и все. Чтобы проверить, работает ли это нормально, запустите ваше приложение, затем откройте терминал и введите —

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,})', sendMovieWithId);

function *sendMovieWithId(next){
   var ctx = this;
   var currMovie = movies.filter(function(movie){
      if(movie.id == ctx.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      this.body = currMovie[0];
   } else {
      this.response.status = 404;//Set status to 404 as movie was not found
      this.body = {message: "Not Found"};
   }
   yield next;
}

Это даст нам фильмы в соответствии с идентификатором, который мы предоставляем. Чтобы проверить это, используйте следующую команду в своем терминале.

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 Route

Используйте следующий маршрут для обработки POST-данных.

router.post('/', addNewMovie);

function *addNewMovie(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name || 
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) || 
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      var newId = movies[movies.length-1].id+1;
      
      movies.push({
         id: newId,
         name: this.request.body.name,
         year: this.request.body.year,
         rating: this.request.body.rating
      });
      this.body = {message: "New movie created.", location: "/movies/" + newId};
   }
   yield next;
}

Это создаст новый фильм и сохранит его в переменной movies. Чтобы проверить этот маршрут, введите в своем терминале следующее:

curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" 
https://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 Route

Маршрут PUT почти такой же, как маршрут POST. Мы будем указывать идентификатор для объекта, который будет обновлен / создан. Создайте маршрут следующим образом —

router.put('/:id', updateMovieWithId);

function *updateMovieWithId(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name || 
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) || 
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !this.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(this.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new movies.push({
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         });
         this.body = {message: "New movie created.", location: "/movies/" + this.params.id};    
      } else {
         //Update existing movie
         movies[updateIndex] = {
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         };
         this.body = {message: "Movie id " + this.params.id + " updated.", location: "/movies/" + this.params.id};
      }
   }
}

Этот маршрут будет выполнять функцию, указанную в таблице выше. Он обновит объект новыми деталями, если он существует. Если он не существует, он создаст новый объект. Чтобы проверить этот маршрут, используйте следующую команду curl. Это обновит существующий фильм. Чтобы создать новый фильм, просто измените идентификатор на несуществующий идентификатор.

curl -X PUT --data "name = Toy%20story&year = 1995&rating = 8.5" 
https://localhost:3000/movies/101

отклик

{"message":"Movie id 101 updated.","location":"/movies/101"}

УДАЛИТЬ Маршрут

Используйте следующий код для создания маршрута удаления.

router.delete('/:id', deleteMovieWithId);

function *deleteMovieWithId(next){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(this.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      this.body = {message: "Not found"};
   } else {
      movies.splice(removeIndex, 1);
      this.body = {message: "Movie id " + this.params.id + " removed."};
   }
}

Протестируйте маршрут так же, как мы это делали для остальных. При успешном удалении (например, идентификатор 105) вы получите —

{message: "Movie id 105 removed."}

Наконец, наш файл movies.js выглядит так:

var Router = require('koa-router');
var router = Router({
   prefix: '/movies'
});  //Prefixed all routes with /movies
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
router.get('/', sendMovies);
router.get('/:id([0-9]{3,})', sendMovieWithId);
router.post('/', addNewMovie);
router.put('/:id', updateMovieWithId);
router.delete('/:id', deleteMovieWithId);

function *deleteMovieWithId(next){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(this.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      this.body = {message: "Not found"};
   } else {
      movies.splice(removeIndex, 1);
      this.body = {message: "Movie id " + this.params.id + " removed."};
   }
}

function *updateMovieWithId(next) {
   //Check if all fields are provided and are valid:
   if(!this.request.body.name ||
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) ||
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !this.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(this.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new
         movies.push({
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         });
         this.body = {message: "New movie created.", location: "/movies/" + this.params.id};
      } else {
         //Update existing movie
            movies[updateIndex] = {
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         };
         this.body = {message: "Movie id " + this.params.id + " updated.", 
            location: "/movies/" + this.params.id};
      }
   }
}

function *addNewMovie(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name ||
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) ||
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      var newId = movies[movies.length-1].id+1;
      
      movies.push({
         id: newId,
         name: this.request.body.name,
         year: this.request.body.year,
         rating: this.request.body.rating
      });
      this.body = {message: "New movie created.", location: "/movies/" + newId};
   }
   yield next;
}
function *sendMovies(next){
   this.body = movies;
   yield next;
}
function *sendMovieWithId(next){
   var ctx = this
   
   var currMovie = movies.filter(function(movie){
      if(movie.id == ctx.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      this.body = currMovie[0];
   } else {
      this.response.status = 404;//Set status to 404 as movie was not found
      this.body = {message: "Not Found"};
   }
   yield next;
}
module.exports = router;

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

Koa.js — Вход

Ведение журнала весьма полезно при создании веб-приложений, поскольку они сообщают нам, где именно что-то пошло не так. Мы также получаем контекст для вещей, которые пошли не так, и можем придумать возможные решения для того же самого.

Чтобы включить регистрацию в Koa, нам понадобится промежуточное программное обеспечение, koa-logger . Установите его с помощью следующей команды.

$ npm install --save-dev koa-logger

Теперь в вашем приложении добавьте следующий код, чтобы включить ведение журнала.

var logger = require('koa-logger')
var koa = require('koa')

var app = koa()
app.use(logger())

app.use(function*(){
   this.body = "Hello Logger";
})

app.listen(3000)

Запустите этот сервер и посетите любой маршрут на сервере. Вы должны увидеть журналы как —

логирование

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

Koa.js — строительные леса

Скаффолдинг позволяет нам легко создавать каркас для веб-приложения . Мы вручную создали наш общедоступный каталог, добавили промежуточное ПО, создали отдельные файлы маршрутов и т. Д. Инструмент скаффолдинга настраивает все эти вещи для нас, чтобы мы могли непосредственно приступить к созданию нашего приложения.

Подмости, которые мы будем использовать, называются Yeoman . Это инструмент для скаффолдинга, созданный для Node.js, но также имеющий генераторы для нескольких других фреймворков (таких как фляга, рейки, django и т. Д.) Чтобы установить yeoman, введите следующую команду в своем терминале.

$ npm install -g yeoman

Yeoman использует генераторы для создания приложений. Чтобы проверить генераторы, доступные на npm для использования с yeoman, зайдите сюда . Для целей этого урока мы будем использовать ‘generator-koa’. Чтобы установить этот генератор, введите следующую команду в своем терминале.

$ npm install -g generator-koa

Чтобы использовать этот генератор, введите —

yo koa

Затем он создаст структуру каталогов и создаст для вас следующие файлы. Он также установит необходимые модули npm и компоненты bower для вас.

create package.json
create test/routeSpec.js
create views/layout.html
create views/list.html
create public/styles/main.css
create public/scripts/.gitkeep
create controllers/messages.js
create app.js
create .editorconfig
create .jshintrc

I'm all done. Running npm install & bower install for you to install 
the required dependencies. 
If this fails, try running the command yourself.

Этот генератор создает для нас очень простую структуру.

.
├── controllers
│   └── messages.js
├── public
|   ├── scripts
|   └── styles
|       └── main.css    
├── test
|   └── routeSpec.js
├── views
|   ├── layout.html
|   └── list.html
├── .editorconfig
├── .jshintrc
├── app.js
└── package.json

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

Koa.js — Ресурсы

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

Koajs.com

Koajs — Примеры Список примеров, созданных сообществом

Список официальных и сторонних промежуточных программ.

API-интерфейс CRUD с использованием koa.js — короткая заставка, рассказывающая о создании API-интерфейса CRUD в Koa.js

Koa.js Quickstart скринкаст

Введение в Koa.js и генераторы