14. Node.JS как веб-сервер

Всем привет, в этой главе мы познакомимся с Node.JS уже в роли веб сервера. Создадим для этого новое приложение. Сейчас я нахожусь в редакторе «WebStorm», в совершенно пустой директории. Первым делом мы  немного настроим проект, мы это уже проходили, посмотреть можно здесь. Далее я создаю файл «server.js»

screenshot_14_01

и в нем, первым делом, подключаю модуль «http». Об этом модуле, мы еще поговорим подробнее, но на текущий момент нам необходим из него один объект. Это «http.Server()», как следует из его названия, он умеет слушать IP и Порт и отвечать на входящие запросы. Для того, чтобы дать ему IP и Порт используется команда «listen()». Ну а для того, чтобы отвечать на запросы, используются события. «http.Server()» является «EventEmitter» и при входящих запросах, соответствующие событие инициируется, которое называется «request», и его обработчик получает два объекта, первый «req» это входящий запрос, он содержит информацию, которую присылает браузер, включая в частности URL пришедшего запроса, и второй параметр «res» это объект ответа, из первого мы читаем во второй пишем. Конкретно наша функция, тут же заканчивает выполнение запроса, отсылая фразу привет мир. Давайте мы посмотрим как это работает. Для этого я создам конфигурацию, смотрим по шагам

screenshot_14_02 screenshot_14_03 screenshot_14_04 screenshot_14_05

screenshot_14_060

screenshot_14_07 screenshot_14_08

Теперь зайдем по этому адресу в нашем браузере — «server.listen(1337, ‘127.0.0.1’);»

screenshot_14_09

Упс, кодировка слетела, давайте  добавим код, который в <head> добавит правильную кодировку

screenshot_14_10

Смотрим

screenshot_14_11

Замечательно, по виду все работает. Чтоб в этом убедиться создадим переменную «counter» которая будет выводить текущий счетчик запросов.

screenshot_14_12

Для проверки в браузере нужно перезагрузить сервер, потому что Node.JS устроен так, что запустившись и считав файл модуля, в данном случае файл «server.js», Node.JS создает из него объект module и этим объектом в дальнейшем пользуется. Соответственно при изменениях данного файла, Node.JS просто не подбирает эти изменения, потому что файл уже обработан. Соответственно, чтобы заставить Node.JS перечитать файл, самый простой способ запустить сервер еще раз. Но если я сейчас нажму Play

screenshot_14_13

То вот, что мы увидим

screenshot_14_14

Ошибка «EADDRINUSE» означает, что адрес уже используется, потому что node server.js попытался запустится еще раз, не прекратив действие уже запущенной программы. Предыдущий сервер  уже занял этот IP и Порт. Что делать? Например можно взять и подредактрировать конфигурацию добавив «Single instance only», ну и имя дадим нашему серверу, заодно

screenshot_14_15 screenshot_14_16

Это означает, что этот сервер может быть запущен в единственном экземпляре. И тогда повторный play убьет текущий запуск, и перезапустит сервер. Если вы в консоле работаете, то это вообще не проблема, прибиваете текущий Node.JS и стартуете новый. В дальнейшем мы посмотрим как это оптимизировать.

И так, теперь перехожу в браузер и нажимаю рестарт. Счетчик увеличивается, но не на один, а на два. Это все потому что браузер устроен так, что вместе со страничкой он делает еще один запрос, этот запрос делается на url «favicon.ico». В данном случае мы никакую favicon не отдаем, поэтому браузер каждый раз его повторяет, поэтому одно обновление страницы приводит к двум запросом. По крайней мере в текущем контексте в хроме. Что ж, мы сделали наш первый серверный Node.JS. В дальнейшем мы будем работать, чтобы сделать его гораздо мощнее и интереснее.

Перед тем как мы продолжим, не большая ремарка. Если вы посмотрите сам сайт Nide.JS то пример аналогичный этому выглядит там немножко по другому, он выглядит так

Основное отличие здесь в том, что мы используем «new Server()», а на сайте «http.createServer()» — это одно и то же. Ну и далее у нас обработчик запросов ставиться явно, а в примере с сайта он передается аргументом. Передача аргументов, это тоже установка обработчика, просто такой дополнительный синтаксис. Он чуть чуть короче, но я выбрал для примера другой синтаксис потому что он более нагляден и показывает то, что реально происходит.

А теперь, если вы внимательно читали, то у вас не вызовет проблемы ответить на следующий небольшой вопрос: в нашем примере есть обработчик событий ‘request’, скажите пожалуйста, как не глядя в документацию сказать какие еще есть события для сервера и когда они вызываются, в каком порядке, при обработке этого запроса?  Почему я прошу не смотреть документацию? Тут две причины, во первых так интересней, во вторых «Server()», вот этот

screenshot_14_17

на самом деле наследует от «net.Server», а он от «EventEmitter».

http.Server -> net.Server -> EventEmitter 

Соответственно некоторые события сервера описаны в «http.Server», а некоторые в документации к «net.Server» и просто взглянув в книгу, понять точный порядок событий, достаточно сложно.  Подсказка находится вот в этой строке — http.Server -> net.Server -> EventEmitter 
Сервер является «EventEmitter», это означает, что все события генерируются вызовом «server.emit» понятно, что мы сами не вызываем этот метод, в данном случае его вызывает сам Node.JS, а мы просто ставим обработчики. Но ничто нам не мешает, чисто джава скриптовым трюком, переопределить этот метод на наш собственный. Метод «emit» принимает название события и необходимые данные для него, в данном случае это будут «req» и «res». Но нас интересует только название события, которое мы при помощи «console.log()» будем выводить. Ну а далее мы будем передавать вызов исходному методу «emit». Посмотрим что получилось, перезапускаем сервер и тут же видим первое  событие «listening», оно означает, что сервер начал слушать соединение.

screenshot_14_18

Далее захожу в браузер и перехожу по адресу «http://127.0.0.1:1337/». А теперь обратите внимание перезагружаю страницу браузера и мы видим, что «request» в консоле WebStorm увеличивается, причем по две штуки, ну мы знаем почему, а «connection» было одно, другое в общем мало.

screenshot_14_19

Потому что событие «connection» возникает тогда, когда браузер открывает к серверу новое соединение, сетевое, а «request» присылает запрос. Браузер устроен так, что одно сетевое соединение он старается использовать по максимуму, называется это «Keep-Alive», он его сохраняет и по нему гонит новые и новые запросы.

Итак, мы создали простейший веб сервер, познакомились с соответствующим объектом «http.Server» и событиями которые в нем возникают.

One thought on “14. Node.JS как веб-сервер”

Обсуждение закрыто.