Статьи

Создание веб-приложения Node с интеграцией Hapi и Twilio

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

Их требования, как правило, включают в себя предоставление людям возможности голосовать с помощью SMS, не позволяя людям голосовать более одного раза и иногда отображать результаты голосования в режиме реального времени. Со временем я создал несколько итераций этого приложения и довольно много узнал о создании веб-приложений с полным стеком с использованием Node и Angular.

В ходе этого урока, состоящего из трех частей, мы собираемся создать веб-приложение Node / Angular с полным стеком с нуля. Вместо того, чтобы создавать упрощенное приложение, мы собираемся создать реальное программное обеспечение, которое интегрируется со сторонним API (Twilio), сохраняет информацию в базе данных (CouchDB), отображает информацию в режиме реального времени (Socket.io). ) и многое, многое другое. В первой части этого урока я расскажу вам:

  1. Создание вашего Node-приложения
  2. Добавление веб-фреймворка Hapi
  3. Интеграция Twilio

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

  • Установить узел
  • Подпишитесь на бесплатную учетную запись разработчика Twilio
  • Установите Ngrok (опционально)

Теперь, когда у вас установлен Node, создать новое приложение Node просто. Сначала откройте терминал. Создайте новый каталог для вашего приложения, перейдите в этот каталог и запустите:

1
npm init

Это проведет вас через процесс создания файла package.json , который определяет основы вашего приложения (имя, зависимости и т. Д.). Не стесняйтесь нажимать ввод в каждой строке, чтобы придерживаться значений по умолчанию. Далее давайте установим веб-фреймворк Hapi:

1
npm install hapi —save

Я выбрал Hapi вместо более популярной платформы Express по двум причинам:

  1. Он предварительно настроен для обработки основных задач веб-приложений (таких как обработка HTTP-тела POST ).
  2. Он одинаково сфокусирован на создании приложений и сервисов.

Создайте новый файл с именем index.js и откройте его в index.js редакторе кода. Давайте пройдемся по нескольким простым строкам кода, чтобы запустить наше приложение:

1
2
var Hapi = require(‘hapi’);
var server = Hapi.createServer(‘localhost’, process.env.PORT || 3000);

Этот код делает модуль Hapi доступным в нашем коде, создает сервер, привязанный к localhost и делает веб-приложение доступным на любом порту, определенном process.env.PORT или 3000 если эта переменная среды не определена. Этот код необходим для того, чтобы при развертывании этого приложения в производственной среде оно связывалось с соответствующим портом. Далее давайте определим маршрут:

1
2
3
4
5
6
7
server.route([{
  method: ‘GET’,
  path: ‘/vote/sms’,
  handler: function (request, reply) {
    reply(‘hello world’);
  }
}]);

Маршрут — это просто кортеж, состоящий из метода HTTP, пути URL и функции-обработчика. Итак, выше, мы говорим Hapi, что если какие-либо GET запросы поступают для пути /vote/sms , отправьте ответ со строкой « hello world ». Теперь добавьте эту последнюю строку:

1
server.start();

Это запустит сервер на вашей машине разработки и прослушит порт 3000 . Сохраните index.js и вернитесь в свой терминал. Запустите ваше приложение так:

1
node .

Наше приложение запущено. Откройте браузер и перейдите по адресу http: // localhost: 3000 / голосование / смс . Вы должны увидеть это:

Это, друзья мои, Hello World с использованием Node и Hapi.

Теперь, когда у нас есть функциональное приложение Node, мы можем начать думать об обработке голосов с помощью SMS. Для этого мы собираемся интегрировать наше приложение Node с Twilio , сторонним API, который позволяет разработчикам легко отправлять и получать текстовые сообщения, совершать и принимать телефонные звонки и встраивать VOIP в свое веб-приложение.

В нашем случае мы хотим обрабатывать входящие текстовые сообщения. Twilio использует конструкцию, известную как webhook, для уведомления веб-приложений о входящих текстовых сообщениях или телефонных звонках. Webhook — это просто URL-адрес, настроенный разработчиком, который вызывается в ответ на происходящее событие. Вот простая схема того, как Twilio webhooks будет работать с нашим приложением Node:

Когда Twilio делает HTTP-запрос (либо GET либо POST , также настраиваемый разработчиком), он также будет включать в себя четко определенный набор параметров, в том числе такую ​​информацию, как источник текстового сообщения, текстовое сообщение и скоро. Когда ваше веб-приложение завершит обработку запроса, Twilio ожидает ответ в виде правильно отформатированного документа TwiML . Этот документ XML предоставляет дополнительные инструкции для выполнения Twilio.

Чтобы упростить работу с API Twilio, давайте установим модуль Twilio NPM . Откройте терминал, перейдите в корневой каталог вашего приложения и выполните следующую команду:

1
npm install twilio —save

Теперь, когда у нас есть общее представление о том, как работает Twilio, давайте создадим URL-адрес, по которому Twilio может звонить, когда приходит SMS-голосование. В каталоге приложения создайте подкаталог с именем routes . В этом новом каталоге создайте новый файл с именем index.js . Этот файл будет содержать логику для маршрутизации URL нашего приложения, так что наш основной файл приложения не будет загроможден. Вы увидите этот шаблон снова и снова, поскольку мы добавляем усложнение нашему приложению. Модульное хранение облегчает понимание и тестирование нашего приложения. Теперь добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
var twilio = require(‘twilio’)
  , Hapi;
 
module.exports = function(hapi) {
  Hapi = hapi
  return exports;
};
 
var voteSMS = exports.voteSMS = function(request, reply) {
  var resp = new twilio.TwimlResponse();
  resp.message(‘Thanks for voting!’);
  reply(resp.toString()).type(‘text/xml’);
};

Здесь происходят три вещи:

  1. Нам нужен модуль Twilio Node
  2. Мы переопределяем module.exports чтобы принять ссылку на Hapi
  3. Определяем обработчик маршрута

Обработчик маршрута немного отличается от первого, который мы написали. В этой итерации мы используем модуль Twilio для создания и заполнения объекта TwimlResponse . Затем мы преобразуем этот объект в String и передаем его методу reply . Наконец, мы явно устанавливаем Content-Type на text/xml . Это станет привычной моделью, когда мы отвечаем на запросы веб-крючков Twilio.

Чтобы завершить этот пример, откройте ваш основной файл index.js (в корне каталога вашего приложения) и добавьте следующую строку кода, где вам требуется модуль Hapi:

1
var routes = require(‘./routes’)(Hapi);

Затем отредактируйте определенный вами маршрут, чтобы удалить анонимную функцию, и замените его ссылкой на routes.voteSMS . Теперь перезапустите ваш Node-сервер и перейдите на страницу http: // localhost: 3000 / voice / sms в вашем браузере. Тебе следует увидеть:

Теперь, когда у нас есть готовый маршрут, следующий шаг — настроить Twilio на запрос этого URL-адреса при поступлении SMS-сообщения. Чтобы это произошло, URL-адрес, который мы предоставляем Twilio, должен быть общедоступным. Настройка Twilio для отправки запроса на localhost не будет работать. В работе ваше приложение будет развернуто на выбранном вами VPS / хосте. Однако было бы замечательно, если бы мы могли отложить развертывание в целях быстрой итеративной разработки. Оказывается, есть замечательный инструмент для этого: Ngrok .

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

Предполагая, что вы установили Ngrok, убедитесь, что сервер Node работает, а затем, в другом терминале, запустите Ngrok:

1
ngrok 3000

Вы должны увидеть такой экран:

Вы можете проверить, действительно ли ваше локальное веб-приложение Node работает в общедоступном Интернете, скопировав следующий URL в ваш браузер: https://YOUR-SUBDOMAIN.ngrok.com/vote/sms . Если вы видите вывод XML из ранее, вы можете идти!

Теперь мы можем настроить Twilio. Войдите в свою учетную запись Twilio, нажмите на вкладку « Числа » и выберите номер для работы. Если вы создали бесплатную учетную запись разработчика, вам должен был быть присвоен номер Twilio. В разделе « Сообщения » установите URL-адрес запроса для URL-адреса Ngrok , включая путь /vote/sms :

Теперь момент истины! Давайте проверим наше приложение, отправив ему текстовое сообщение. Выньте свой мобильный телефон и отправьте текстовое сообщение на ваш номер Twilio. Вы можете отправить любое сообщение, которое вы хотите. Через пару секунд вы должны увидеть ответ:

Проницательные из вас могли заметить небольшую проблему безопасности с нашим приложением. Что может помешать злоумышленнику выяснить URL-адрес вашего webhook, а затем имитировать Twilio, отправляя свои собственные HTTP-запросы? Это кажется довольно простым способом заполнить урну для голосования. К счастью, Twilio предвосхитил необходимость защищать веб-крючков, а модуль Twilio Node предоставляет метод для проверки того, что HTTP-запрос действительно поступает от Twilio.

Во-первых, вам понадобится ваш токен авторизации . Каждая учетная запись Twilio имеет SID учетной записи и токен авторизации. Они вроде как имя пользователя и пароль, но для программного доступа API к вашей учетной записи. Если вы вошли на веб-сайт Twilio, вы найдете обе эти информации на своей панели инструментов:

Нажмите на значок замка, чтобы открыть свой токен авторизации. Затем выберите его и скопируйте в буфер обмена. Затем создайте файл в каталоге вашего app именем config.js . Добавьте следующие строки:

1
2
3
4
5
6
7
var config = {};
 
config.twilio = {};
config.twilio.key = ‘yyy’;
config.twilio.disableSigCheck = false;
 
module.exports = config;

Теперь откройте routes.js и импортируйте наш новый модуль конфигурации, добавив следующую строку в начало файла:

1
var config = require(‘../config’);

voteSMS небольшую модификацию в наш маршрут voteSMS :

01
02
03
04
05
06
07
08
09
10
var voteSMS = exports.voteSMS = function(request, reply) {
  if (fromTwilio(request) || config.twilio.disableSigCheck) {
    var resp = new twilio.TwimlResponse();
    resp.message(‘Thanks for voting!’);
    reply(resp.toString()).type(‘text/xml’);
  }
  else {
    reply(Hapi.error.unauthorized(‘Sorry, no black hats allowed’));
  }
};

Все, что мы делаем, это вызываем функцию, чтобы узнать, действительно ли запрос поступил от Twilio. Если это так, тогда продолжайте. Если это не так, верните клиенту ошибку 403 Unauthorized error. Функция fromTwilio довольно проста:

1
2
3
4
5
6
7
var fromTwilio = function(request) {
  var sig = request.headers[‘x-twilio-signature’]
    , url = config.twilio.messagingUrl + request.url.search
    , body = request.payload ||
 
  return twilio.validateRequest(config.twilio.authToken, sig, url, body);
};

Здесь мы просто используем метод validateRequest модуля Twilio Node, чтобы проверить, поступил ли запрос от Twilio. Тем, кто заинтересован, следует больше узнать о его реализации , но давайте двигаться дальше. Функция принимает четыре параметра: ваш токен аутентификации Twilio, значение заголовка, передаваемое Twilio, полный URL-адрес, который вызывал Twilio (включая любые параметры GET ), и тело POST (пустое, если это не был запрос POST ). Он вернет true если запрос поступил от Twilio, и false противном случае.

Это легко проверить, если это работает. Сначала отправьте SMS на свой номер Twilio и посмотрите, получите ли вы ответ. Затем откройте браузер и попробуйте открыть URL. Вы должны увидеть это:

Обеспеченные!

И это все для первой части этого руководства по созданию полнофункциональных веб-приложений Node и Angular.

Начиная с нуля мы имеем:

  • Создано веб-приложение Node
  • Добавлен веб-фреймворк Hapi
  • Построен маршрут для возврата XML
  • Использовал Twilio для маршрутизации входящих текстовых сообщений в наше приложение
  • Защищенный URL, чтобы принимать запросы только от Twilio

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