Статьи

Познакомьтесь с Connect Framework

Новички в NodeJS обычно находят, что его API трудно понять. К счастью, многие разработчики создали фреймворки, облегчающие работу с Node. Connect является одной из таких рамок. Он находится поверх API-интерфейса Node и проводит границу между комфортом и контролем.

Думайте о Connect как о стеке промежуточного программного обеспечения. С каждым запросом Connect фильтрует слои промежуточного программного обеспечения, каждый из которых имеет возможность обрабатывать HTTP-запрос. Когда TJ Holowaychuk объявил о Connect , он сказал, что существует два типа промежуточного программного обеспечения. Первый фильтр .

Фильтры обрабатывают запрос, но не отвечают на него (подумайте о ведении журнала на сервере).

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


Во-первых, вам нужно установить пакет Connect через npm:

1
npm install connect

Теперь создайте файл server.js и добавьте следующий код:

Переменная connect — это функция, которая возвращает новое приложение Connect. Итак, наш следующий шаг — создать это приложение:

Вам не нужно создавать переменную app для большинства ваших приложений. Функции, вовлеченные в создание приложения ( connect() и use() ), являются цепными:

Функция use() добавляет слой промежуточного программного обеспечения в приложение, а функция listen() сообщает нашему приложению, что нужно начинать принимать соединения через указанный порт (3000 в нашем примере).

Давайте начнем с чего-то простого: регистрация. Код для приложения Connect, использующего только промежуточное программное обеспечение для ведения журналов, довольно прост:

По умолчанию Node анализирует очень мало входящего запроса.

Добавьте этот код в свой файл и запустите сервер, запустив node server.js . Перейдите к любому пути в вашем браузере и проигнорируйте результаты «Cannot GET …». Нас не интересует, что сервер отправил обратно в браузер; мы заинтересованы в журнале сервера. Посмотрите на терминал, и вы увидите журнал ваших запросов. Обязательно ознакомьтесь с документацией регистратора для получения информации о его других функциях и настройках.

Это был фильтр; Теперь давайте посмотрим на поставщика. Простейшим поставщиком является статический поставщик; он обслуживает статические файлы из указанной папки. Вот его синтаксис:

Вероятно, вы можете угадать назначение переменной Node __dirname : это путь к текущему каталогу. Это промежуточное ПО статически обслуживает что-либо из общей папки в текущем каталоге. Итак, создайте public/page.html и добавьте элемент <h1> . Перезапустите сервер ( node server.js ) и перейдите к localhost:3000/page.html в вашем браузере. Вы должны page.html визуализировать в браузере.

Теперь давайте кратко рассмотрим некоторые другие варианты промежуточного программного обеспечения Connect.


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

  • connect.json() анализирует тела запросов JSON (где content-type является application/json ).
  • connect.urlencoded() анализирует тела запросов x-ww-form-urlencoded .
  • connect.multipart() анализирует тела запросов multipart/form-data .
  • connect.bodyParser() является ярлыком для включения всех трех выше.

Использование любого из этих фильтров дает вам возможность получить доступ к вашему проанализированному телу через request.body (мы скоро поговорим о том, как получить этот объект request ).

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


Файлы cookie и сеансы являются важной частью любого веб-приложения, и есть несколько промежуточных программ, которые помогают управлять ими. connect.cookieParser() анализирует файлы cookie для вас, и вы можете получить файлы cookie и их значения через объект request.cookies . Это более полезно, если вы добавляете фильтр connect.session() в свое приложение. Этот фильтр требует, чтобы парсер cookie уже был на месте. Вот небольшой пример:

Каждая функция промежуточного программного обеспечения, которую вы пишете, должна либо передавать запрос на next уровень, либо отвечать на запрос.

После cookieParser мы включаем фильтр session и передаем ему две опции:

  • secret создает подписанный файл cookie, который отслеживает сеанс.
  • cookie.maxAge определяет продолжительность жизни в миллисекундах; 30000 в этом коде составляет 30 секунд.

В последнем вызове use() мы передаем функцию, которая отвечает на запрос. Мы используем два свойства из объекта request : req.session для данных сеанса и req.url для URL запроса.

Если приложение получает запрос на /name/some_name , оно сохраняет значение some_name в req.session.name . Все, что хранится в сеансе, может быть получено в последующих запросах для продолжительности нашего сеанса. Любые запросы к /name/other заменяют переменную сеанса, а любые запросы к другим URL-адресам выводят значение переменной сеанса и время, оставшееся для сеанса.

Таким образом, вы можете перейти к localhost:3000/name/your_name , а затем перейти к localhost:3000 чтобы увидеть your_name . Обновите страницу несколько раз и посмотрите, сколько секунд отсчитывается. Когда сессия истечет, вы увидите сообщение по умолчанию «нет сохраненного имени».

Я упомянул, что фильтр cookieParser должен быть до session .

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

Поскольку session нужны проанализированные данные cookie, запрос должен пройти через cookieParser перед session .

Я мог бы объяснить все остальные встроенные компоненты промежуточного программного обеспечения, но я упомяну еще несколько, прежде чем писать собственный код для взаимодействия с Connect.

  • сжатие : промежуточное программное обеспечение сжатия Gzip
  • basicAuth : базовая аутентификация http
  • каталог : список каталогов промежуточного программного обеспечения
  • errorHandler : гибкий обработчик ошибок

Вы только что узнали, как написать свой собственный код с Connect. Вот основной синтаксис еще раз:

Три параметра функции важны; они обеспечивают доступ к внешнему миру. Параметр req , конечно, является объектом запроса, а res является ответом. Третий параметр, next , является ключом к созданию функций, которые хорошо работают в стеке промежуточного программного обеспечения. Это функция, которая передает запрос следующему промежуточному программному обеспечению в стеке. Смотрите этот пример:

Этот код использует две функции промежуточного программного обеспечения. Первая функция проверяет метод запроса, чтобы увидеть, является ли это запросом POST. Если это так, он отвечает, говоря так. В противном случае мы вызываем next() и передаем запрос следующей функции, которая отвечает независимо от того, что. Используйте curl для проверки обоих слоев в терминале:

1
2
3
4
5
$ curl http://localhost:3000
This is not a POST request (probably a GET request)
 
$ curl -X POST http://localhost:3000
This is a POST request

Если вам не нравится терминал, попробуйте этот полезный плагин Chrome .

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

А как насчет этих параметров request и response ? Это те же самые объекты запросов и ответов, которые вы получаете при использовании «сырого» Node-сервера:

Если вы раньше не использовали серверный API Node, позвольте мне показать вам, что вы можете с ним сделать.


Объект request самом деле является объектом http.IncomingMessage , и его важные свойства перечислены ниже:

  • req.method сообщает вам, какой метод HTTP был использован.
  • req.url сообщает вам, какой URL был запрошен.
  • req.headers — это объект с именами и значениями заголовков.
  • req.query — это объект с любыми данными в строке запроса (для его анализа вам понадобится промежуточное программное обеспечение connect.query() ).
  • req.body — это объект данных формы (вам понадобится некоторое промежуточное программное обеспечение для разбора тела).
  • req.cookies является объектом данных cookie (требует разбора cookie).
  • req.session является объектом данных сеанса (опять же, вам понадобится разбор req.session cookie и промежуточное программное обеспечение сеанса).

Вы можете увидеть все это при работе со следующим кодом:

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

1
curl -X POST -d «name=YourName» «http://localhost:3000/some/url?some=data»

С этими семью свойствами вы можете управлять практически любым запросом, который получите. Я не думаю, что трейлеры используются часто (я никогда не видел их в своем опыте), но вы можете использовать req.trailers если ожидаете их в своих запросах (трейлеры похожи на заголовки, но после тела).

Итак, как насчет вашего ответа?


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

Начнем с кода состояния и заголовков ответов. Вы можете установить их все сразу, используя метод writeHead() . Вот пример из документации по Node:

Если вам нужно индивидуально установить заголовки, вы можете использовать метод setHeader() :

Добавьте этот код в файл, запустите сервер и запросите его в браузере. Вы получили HTML! Теперь запустите:

1
curl http://localhost:3000

И вы получите простой текст. Для JSON попробуйте это:

1
curl -H «accept:application/json» http://localhost:3000

Все с одного URL!

Используйте res.getHeader(name) если вам нужно знать, какие заголовки уже установлены. Вы также можете использовать res.removeHeader(name) для удаления заголовка.

Конечно, ответ бесполезен без тела. Как вы видели в этом руководстве, вы можете записывать куски данных в тело с помощью res.write() . Это принимает строку или буферный объект в качестве аргумента. Если это строка, вторым параметром является тип кодировки (по умолчанию это utf8 ).

Метод res.end() закрывает тело, но вы можете передать ему данные для записи в поток ответов. Это полезно в ситуациях, когда вам нужно вывести только одну строку.


Сложно ответить большими HTML-телами в простом старом Node и Connect. Это хорошее место для добавления стороннего промежуточного программного обеспечения. Вы можете найти список стороннего промежуточного программного обеспечения на вики-сайте Connect Github . В качестве примера мы собираемся использовать пакет connect-jade , который позволяет нам рендерить нефритовые представления.

Сначала установите connect-jade :

1
npm install connect-jade

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

Установите корень как каталог, который содержит файлы представления. Вы также можете установить defaults ; это переменные, которые доступны внутри каждого представления, если мы не переопределим их позже при вызове render() .

Последняя функция в этом коде делает вызов res.render() . Этот метод предоставляется пакетом connect-jade .

Первый аргумент, который он принимает, — это имя представления для отображения.

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

1
2
3
4
5
html
 head
   title= title
 body
   h1= heading

Если вы не знакомы с jade , мы сделаем отступ для имен тегов, чтобы создать структуру HTML. Знак равенства возвращает значение переменной JavaScript. Эти переменные берутся из defaults по defaults мы установили, плюс (необязательный) объект второго параметра, переданный в res.render() .

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


Если вы разберетесь в том, как работает Connect, вы обнаружите, что каждый слой на самом деле является модулем Node — очень продуманный дизайн. Если вы используете Connect для больших приложений, было бы идеально написать код в формате модуля Node. Вы могли бы иметь файл app.js как это:

И в вашем server.js :


Если вам нужна библиотека для начинающих, которая позволяет легко создавать большие веб-приложения, то Connect — не ваше решение. Connect представляет собой тонкий слой поверх необработанного Node API, который дает вам полный контроль над вашим серверным приложением. Если вы хотите немного больше, я рекомендую Express (между прочим, кстати). В противном случае Connect — это фантастическая расширяемая библиотека для веб-приложений Node.