Перейти к содержимому

Как выглядит основной файл сервера на node js

  • автор:

Сервер

Для работы с сервером и протоколом http в Node.js используется модуль http.

Чтобы создать сервер, следует вызвать метод http.createServer() :

const http = require("http"); http.createServer().listen(3000);

Метод createServer() возвращает объект http.Server . Но чтобы сервер мог прослушивать и обрабатывать входящие подключения, у объекта сервера необходимо вызвать метод listen() , в который в качестве параметра передается номер порта, по которому запускается сервер.

Для обработки подключений в метод createServer можно передать специальную функцию:

const http = require("http"); http.createServer(function(request, response)< response.end("Hello world!"); >).listen(3000);

Эта функция принимает два параметра:

  • request : хранит информацию о запросе
  • response : управляет отправкой ответа

Request

Параметр request позволяет получить информацию о запросе и представляет объект http.IncomingMessage . Отметим некоторые основные свойства этого объекта:

  • headers : возвращает заголовки запроса
  • method : тип запроса (GET, POST, DELETE, PUT)
  • url : представляет запрошенный адрес

Например, определим следующий файл app.js:

var http = require("http"); http.createServer(function(request, response)< console.log("Url: " + request.url); console.log("Тип запроса: " + request.method); console.log("User-Agent: " + request.headers["user-agent"]); console.log("Все заголовки"); console.log(request.headers); response.end(); >).listen(3000);

Запустим его и обратимся в браузере по адресу http://localhost:3000/index.html :

Обработка запроса в Node.js

Response

Параметр response управляет отправкой ответа и представляет объект http.ServerResponse . Среди его функциональности можно выделить следующие методы:

  • statusCode : устанавливает статусный код ответа
  • statusMessage : устанавливает сообщение, отправляемое вместе со статусным кодом
  • setHeader(name, value) : добавляет в ответ один заголовок
  • write : пишет в поток ответа некоторое содержимое
  • writeHead : добавляет в ответ статусный код и набор заголовков
  • end : сигнализирует серверу, что заголовки и тело ответа установлены, в итоге ответ отсылается клиента. Данный метод должен вызываться в каждом запросе.

Например, изменим файл app.js следующим образом:

const http = require("http"); http.createServer(function(request, response)< response.setHeader("UserId", 12); response.setHeader("Content-Type", "text/html; charset=utf-8;"); response.write("

hello world

"); response.end(); >).listen(3000);

Запустим файл и обратимся в браузере к приложению:

Отправка ответа в Node.js

Если предстоит отправить довольно большой ответ, то мы можем несколько раз вызвать метод write() , последовательно оправляя в исходящий поток каждый кусочек информации. Например, отправим код более менее полноценной веб-страницы:

const http = require("http"); http.createServer(function(request, response)< response.setHeader("Content-Type", "text/html"); response.write(""); response.write(""); response.write(""); response.write("Hello Node.js"); response.write(""); response.write(""); response.write("

Привет миг

"); response.write(""); response.end(); >).listen(3000);
Маршрутизация

По умолчанию Node.js не имеет встроенной системы маршрутизации. Обычно она реализуется с помощью специальных фреймворках типа Express, о котором речь пойдет в следующей главе. Однако если необходимо разграничить простейшую обработку пары-тройки маршрутов, то вполне можно использовать для этого свойство url объекта Request. Например:

const http = require("http"); http.createServer(function(request, response)< response.setHeader("Content-Type", "text/html; charset=utf-8;"); if(request.url === "/home" || request.url === "/")< response.write("

Home

"); > else if(request.url == "/about")< response.write("

About

"); > else if(request.url == "/contact")< response.write("

Contacts

"); > else< response.write("

Not found

"); > response.end(); >).listen(3000);

В данном случае обрабатываются три маршрута. Если идет обрашение к корню сайта или по адресу localhost:3000/home , то пользователю выводится строка «Home». Ели обращение идет по адресу localhost:3000/about , то пользователю в браузере отображается строка About и так далее. Если запрошенный адрес не соответствует ни одному маршруту, то выводится заговлок «Not Found».

Маршрутизация в Node.js

Однако опять же отмечу, что рамках специальных фреймворков, которые работают поверх Node.js, например, Express, есть более удобные способы для обработки маршрутов, которые нередко и используются.

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

Переадресация предполагает отправку статусного кода 301 (постоянная переадресация) или 302 (временная переадресация) и заголовка Location , который указывает на новый адрес. Например, выполним переадресацию с адреса localhost:3000/ на адрес localhost:3000/newpage

const http = require("http"); http.createServer(function(request, response) < response.setHeader("Content-Type", "text/html; charset=utf-8;"); if(request.url === "/")< response.statusCode = 302; // временная переадресация // на адрес localhost:3000/newpage response.setHeader("Location", "/newpage"); >else if(request.url == "/newpage") < response.write("New address"); >else < response.statusCode = 404; // адрес не найден response.write("Not Found"); >response.end(); >).listen(3000);

Node.js server without a framework

Здесь вы найдёте описание простого статического сервера, который построен сугубо на Node.js без использования какого-либо фреймворка .

Node.js может использовать множество фреймворков, которые могут помочь создать сервер

  • Express: Один из наиболее популярных фреймворков.
  • Hapi.js: Набирающий популярность фреймворк для построения приложений и сервисов
  • Total: Этот фреймворк имеет богатую функциональность и не требует каких-либо дополнительных фреймворков или библиотек.

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

Пример

Вот так выглядит статический сервер на Node.js:

var http = require("http"); var fs = require("fs"); var path = require("path"); http .createServer(function (request, response)  console.log("request ", request.url); var filePath = "." + request.url; if (filePath == "./")  filePath = "./index.html"; > var extname = String(path.extname(filePath)).toLowerCase(); var mimeTypes =  ".html": "text/html", ".js": "text/javascript", ".css": "text/css", ".json": "application/json", ".png": "image/png", ".jpg": "image/jpg", ".gif": "image/gif", ".svg": "image/svg+xml", ".wav": "audio/wav", ".mp4": "video/mp4", ".woff": "application/font-woff", ".ttf": "application/font-ttf", ".eot": "application/vnd.ms-fontobject", ".otf": "application/font-otf", ".wasm": "application/wasm", >; var contentType = mimeTypes[extname] || "application/octet-stream"; fs.readFile(filePath, function (error, content)  if (error)  if (error.code == "ENOENT")  fs.readFile("./404.html", function (error, content)  response.writeHead(404,  "Content-Type": "text/html" >); response.end(content, "utf-8"); >); > else  response.writeHead(500); response.end( "Sorry, check with the site admin for error: " + error.code + " ..\n", ); > > else  response.writeHead(200,  "Content-Type": contentType >); response.end(content, "utf-8"); > >); >) .listen(8125); console.log("Server running at http://127.0.0.1:8125/"); 

Задание

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

Found a content problem with this page?

  • Edit the page on GitHub.
  • Report the content issue.
  • View the source on GitHub.

This page was last modified on 3 авг. 2023 г. by MDN contributors.

Свой веб-сервер на NodeJS, и ни единого фреймворка. Часть 1

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

Новичку в NodeJS действительно может быть нелегко. JS — один из языков, в котором часто не существует единственного правильного решения конкретной задачи, а добавленные в ноду модули для работы с файловой системой, http сервером и прочими вещами, характерными для работы на сервере, затрудняют переход даже тем, кто пишет хороший код для браузеров. Тем не менее, я надеюсь, что вы знаете основы этого языка и его работы в серверном окружении, если нет, советую посмотреть замечательный скринкаст, который поможет разобраться в основах. И последнее — я не претендую на какой-то исключительно правильный код и буду рад услышать критику — мы все учимся, и это отличный способ получать знания.

Начнём с файловой структуры

Исходная папка nodejs хранится на сервере по пути /var/www/html/. В ней и будет наш веб-сервер. Дальше всё просто: создаём в ней директорию routing, в которой будет лежать наш скрипт index.js, а также 4 папки — dynamic, static, nopage и main — для динамически генерируемых страниц, статики, страницы 404 и главной страницы. Выглядит всё это так:

nodejs
—routing
—-dynamic
—-nopage
—-static
—-main
—-index.js

Создаём наш сервер

Отлично, с файловой структурой более-менее определились. Теперь создаём в исходной папке файл server.js со следующим содержимым:

// server.js // Для начала установим зависимости. const http = require('http'); const routing = require('./routing'); let server = new http.Server(function(req, res) < // API сервера будет принимать только POST-запросы и только JSON, так что записываем // всю нашу полученную информацию в переменную jsonString var jsonString = ''; res.setHeader('Content-Type', 'application/json'); req.on('data', (data) =>< // Пришла информация - записали. jsonString += data; >); req.on('end', () => ); >); server.listen(8000, 'localhost'); 

Здорово! Теперь наш сервер будет принимать запросы, записывать JSON-данные, если они есть, но пока что будет вылетать с ошибкой, потому что у нас нет функции define в /routing/index.js. Время это исправить.

// /routing/index.js const define = function(req, res, postData) < res.end('Hello, Habrahabr!'); >exports.define = define; 

Запускаем наш сервер:

node server.js

Заходим туда, где он слушает запросы. Если вы не меняли код, это будет localhost:8000. Ура. Ответ есть.

image

Замечательно. Только это не совсем то, что нам нужно от сервера, правда?

Ловим запросы к нашим API

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

// /routing/index.js // Для начала установим зависимости. const url = require('url'); const fs = require('fs'); const define = function(req, res, postData) < // Теперь получаем наш адрес. Если мы переходим на localhost:3000/test, то path будет '/test' const urlParsed = url.parse(req.url, true); let path = urlParsed.pathname; // Теперь записываем полный путь к server.js. Мне это особенно нужно, так как сервер будет // висеть в systemd, и путь, о котором он будет думать, будет /etc/systemd/system/. prePath = __dirname; try < // Здесь мы пытаемся подключить модуль по ссылке. Если мы переходим на // localhost:8000/api, то скрипт идёт по пути /routing/dynamic/api, и, если находит там // index.js, берет его. Я знаю, что использовать тут try/catch не слишком правильно, и потом // переделаю через fs.readFile, но пока у вас не загруженный проект, разницу в скорости // вы не заметите. let dynPath = './dynamic/' + path; let routeDestination = require(dynPath); res.end('We have API!'); >catch (err) < // Не нашлось api? Грустно. res.end("We don't have API!"); >>; exports.define = define; 

Готово. Теперь мы можем создать /routing/dynamic/api , и протестировать то, что у нас есть. Я воспользуюсь для этих целей своим готовым скриптом по адресу /dm/shortenUrl.

image

Определяем, есть ли страница

Мы научились находить скрипты, теперь нужно научиться находить статику. Первым делом пойдём в /routing/nopage и создадим там index.html . Просто создайте костяк html-страницы, и сделайте один-единственный заголовок h1 с текстом: «404». После этого возвращаемся в /routing/index.js , но теперь мы сосредоточимся на уже написанном блоке catch:

// /routing/index.js: блок catch catch (err) < // Находим наш путь к статическому файлу и пытаемся его прочитать. // Если вы не знаете, что это за '=>', тогда прочитайте про стрелочные функции в es6, // очень крутая штука. let filePath = prePath+'/static'+path+'/index.html'; fs.readFile(filePath, 'utf-8', (err, html) => < // Если не находим файл, пытаемся загрузить нашу страницу 404 и отдать её. // Если находим — отдаём, народ ликует и устраивает пир во имя царя-батюшки. if(err) < let nopath = '/var/www/html/nodejs/routing/nopage/index.html'; fs.readFile(nopath, (err , html) =>< if(!err) < res.writeHead(404, ); res.end(html); > // На всякий случай напишем что-то в этом духе, мало ли, иногда можно случайно // удалить что-нибудь и не заметить, но пользователи обязательно заметят. else< let text = "Something went wrong. Please contact webmaster@forgetable.ru"; res.writeHead(404, ); res.end(text); > >); > else< // Нашли файл, отдали, страница загружается. res.writeHead(200, ); res.end(html); > >); > 

Воодушевляет. Теперь мы можем отдавать страницу 404, а так же html-страницы, которые мы добавляем сами в /routing/static . В моём случае страница 404 выглядит так:

image

Пара слов об API

Способ организации скриптов — личное дело каждого. На данный момент код в блоке try у меня такой:

let dynPath = './dynamic/' + path; let routeDestination = require(dynPath); routeDestination.promise(res,postData,req).then( result => < res.writeHead(200); res.end(result); return; >, error => < let endMessage = <>; endMessage.error = 1; endMessage.errorName = error; res.end(JSON.stringify(endMessage)); return; > ); 

По сути, все мои скрипты представляют собой функцию, которая передаёт замыканиями параметры и возвращает промис, и дальнейшая логика на промисах и завязана. В данном контексте такой подход кажется мне очень удобным, так отлов ошибок становится очень лёгким делом. Уже можно, в принципе, переписать эту логику на async / await, но особого смысла для себя я в этом не вижу.

Обрабатываем запросы браузера

Теперь мы уже можем пользоваться нашим сервером, и он будет возвращать страницы. Однако, если вы поместите в /routing/static/somepage ту же страницу, которая прекрасно работает, например, на апаче, вы столкнётесь с некоторыми проблемами.

Во-первых, для этого веб-сервера, как и для, наверное, всех в таком роде, нужно иначе задавать ссылки на css/js/img/… файлы. Если вам хочется подключить к странице 404 css-файл и сделать её красивой, то в случае с апачем мы создали бы в той же папке nopage файл style.css и подключили бы его, указав в тэге link следующее: ‘href=«style.css»’. Однако, теперь нам нужно писать путь иначе, а именно: «/routing/nopage/style.css».

Во-вторых, даже если мы подключим всё правильно, то ничего не произойдёт, и у нас всё ещё будет голая страница html. И вот тут мы подходим к самой последней части сегодняшней статьи — дополним скрипт, чтобы он ловил и обрабатывал запросы, которые браузер отправляет сам, читая разметку html. Ну и про favicon не забудем — возьмите фавиконку и положите её в /routing директорию нашего сервера.

Итак, переходим опять в /routing/index.js . Теперь мы будем писать код прямо перед try/catch:

// До этого мы уже получили path и prePath. Теперь осталось понять, какие запросы // мы получаем. Отсеиваем все запросы по точке, так чтобы туда попали только запросы к // файлам, например: style.css, test.js, song.mp3 if(/\./.test(path)) < if(path == 'favicon.ico') < // Если нужна фавиконка - возвращаем её, путь для неё всегда будет 'favicon.ico' // Получается, если добавить в начале prePath, будет: '/var/www/html/nodejs/routing/favicon.ico'. // Не забываем про return, чтобы сервер даже не пытался искать файлы дальше. let readStream = fs.createReadStream(prePath+path); readStream.pipe(res); return; >else< // А вот если у нас не иконка, то нам нужно понять, что это за файл, и сделать нужную // запись в res.head, чтобы браузер понял, что он получил именно то, что и ожидал. // На данный момент мне нужны css, js и mp3 от сервера, так что я заполнил только // эти случаи, но, на самом деле, стоит написать отдельный модуль для этого. if(/\.mp3$/gi.test(path)) < res.writeHead(200, < 'Content-Type': 'audio/mpeg' >); > else if(/\.css$/gi.test(path)) < res.writeHead(200, < 'Content-Type': 'text/css' >); > else if(/\.js$/gi.test(path)) < res.writeHead(200, < 'Content-Type': 'application/javascript' >); > // Опять же-таки, отдаём потом серверу и пишем return, чтобы он не шёл дальше. let readStream = fs.createReadStream(prePath+path); readStream.pipe(res); return; > > 

Фух. Всё готово. Теперь можно подключить наш css-файл и увидеть нашу страницу 404 со всеми стилями:

image

Выводы

Ура! Мы сделали свой веб-сервер, который работает, и работает хорошо. Разумеется, это только начало работы над приложением, но самое главное уже готово — на таком веб-сервере можно поднимать любые страницы, он справляется и со статикой, и с динамическим контентом, и роутинг, на мой взгляд, выглядит удобно — достаточно просто положить соответствующий файл в static или dynamic, и он тут же подхватится, и не надо писать роутинг для каждого конкретного случая.

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

UPD: Я не призываю кого-либо использовать этот сервер на постоянной основе. Несмотря на то, что он полностью меня устраивает, в нём нет большого количества нужных для обычного веб-сервера функций и не оптимизирован некоторый готовый функционал, вроде внятного определения mime-типов. Это всё будет в следующих статьях.

Руководство для начинающих по серверной веб-разработке с Node.js

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

Этот пост представляет собой описание того, как я узнал больше о веб-разработке на стороне сервера с помощью Node.js, и краткое сравнение написания простого HTTP-сервера с использованием 3 разных сред, Express, Koa.js и Hapi.js.

Примечание: если вы опытный разработчик Node.js, вы, вероятно, подумаете о том, что это все элементарно/просто. ¯\_(ツ)_/¯.

Некоторые основы сети

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

Мне очень понравился этот курс, потому что он объяснял, что происходило под капотом, в понятной форме, поэтому, если вы можете взять в руки учебник «Компьютерные сети», прочитайте все подробности о чудесах сети.

image

Здесь, однако, я собираюсь лишь кратко рассказать о контексте. HTTP (Hypertext Transfer Protocol) — это протокол связи, используемый в компьютерных сетях. В Интернете их много, таких как SMTP (простой протокол передачи почты), FTP (протокол передачи файлов), POP3 (протокол почтового отделения 3) и так далее.

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

image

От TCP / IP против OSI: в чем разница между двумя моделями?

Операционные системы обычно поставляются с поддержкой сетевых протоколов, таких как HTTP, из коробки, что объясняет, почему нам не нужно явно устанавливать какое-либо дополнительное программное обеспечение для доступа в Интернет. Большинство сетевых протоколов поддерживают открытое соединение между двумя устройствами, что позволяет им передавать данные туда и обратно.

HTTP, на котором работает сеть, отличается. Он известен как протокол без установления соединения, потому что он основан на режиме работы запрос / ответ. Веб-браузеры отправляют на сервер запросы на изображения, шрифты, контент и т.д., но после выполнения запроса соединение между браузером и сервером разрывается.

image

Servers and Clients

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

Сегодня мы поговорим о программной стороне вещей. Но сначала несколько определений. URL обозначает Universal Resource Locator и состоит из 3 частей: протокола, сервера и запрашиваемого файла.

image

Структура URL адреса

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

Сервер должен знать, как обрабатывать этот HTTP-запрос, чтобы получить правильный файл, а затем отправить его обратно браузеру, который его запросил. Наиболее популярное программное обеспечение веб-сервера, которое обрабатывает это Apache и NGINX.

image

Веб-серверы обрабатывают входящие запросы и отвечают на них соответственно

Оба представляют собой полнофункциональные пакеты программного обеспечения с открытым исходным кодом, которые включают в себя такие функции, как схемы аутентификации, перезапись URL-адресов, ведение журнала и проксирование, и это лишь некоторые из них. Apache и NGINX написаны на C. Технически, вы можете написать веб-сервер на любом языке. Python, golang.org/pkg/net/http, Ruby, этот список может продолжаться довольно долго. Просто некоторые языки лучше выполняют определенные вещи, чем другие.

Создание HTTP сервера с Node.js

Node.js — это среда выполнения Javascript, построенная на движке Chrome V8 Javascript. Он поставляется с модулем http, который предоставляет набор функций и классов для построения HTTP-сервера.

Для этого базового HTTP-сервера мы также будем использовать файловую систему, путь и URL-адрес, которые являются собственными модулями Node.js.

Начните с импорта необходимых модулей.

const http = require('http') // Чтобы использовать HTTP-интерфейсы в Node.js const fs = require('fs') // Для взаимодействия с файловой системой const path = require('path') // Для работы с путями файлов и каталогов const url = require('url') // Для разрешения и разбора URL 

Мы также создадим словарь типов MIME, чтобы мы могли назначить соответствующий тип MIME запрашиваемому ресурсу на основе его расширения. Полный список типов MIME можно найти в Internet Assigned Numbers Authority (интернет-центре назначенных номеров).

const mimeTypes = < '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.ico': 'image/x-icon', '.png': 'image/png', '.jpg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.json': 'application/json', '.woff': 'font/woff', '.woff2': 'font/woff2' >

Теперь мы можем создать HTTP-сервер с функцией http.createServer() , которая будет возвращать новый экземпляр http.Server .

const server = http.createServer()

Мы передадим функцию-обработчик запроса в createServer() с объектами запроса и ответа. Эта функция вызывается один раз каждый раз, когда к серверу поступает HTTP-запрос.

server.on('request', (req, res) => < // здесь нужно сделать больше >) 

Сервер запускается путем вызова метода listen объекта server с номером порта, который мы хотим, чтобы сервер прослушивал, например, 5000 .

server.listen(5000)

Объект request является экземпляром IncomingMessage и позволяет нам получать доступ ко всей информации о запросе, такой как статус ответа, заголовки и данные.

Объект response является экземпляром ServerResponse, который является записываемым потоком и предоставляет множество методов для отправки данных обратно клиенту.

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

    Разобрать входящий запрос и обработать его без расширений

const parsedUrl = new URL(req.url, 'https://node-http.glitch.me/') let pathName = parsedUrl.pathname let ext = path.extname(pathName) // Для обработки URL с конечным символом '/', удаляем вышеупомянутый '/' // затем перенаправляем пользователя на этот URL с помощью заголовка 'Location' if (pathName !== '/' && pathName[pathName.length - 1] === '/') < res.writeHead(302, ) res.end() return > // Если запрос для корневого каталога, вернуть index.html // В противном случае добавляем «.html» к любому другому запросу без расширения if (pathName === '/') < ext = '.html' pathName = '/index.html' >else if (!ext)
// Создаем правильный путь к файлу, чтобы получить доступ к соответствующим ресурсам const filePath = path.join(process.cwd(), '/public', pathName) // Проверяем, существует ли запрошенный ресурс на сервере fs.exists(filePath, function (exists, err) < // Если запрошенный ресурс не существует, ответим 404 Not Found if (!exists || !mimeTypes[ext]) < console.log('Файл не найден: ' + pathName) res.writeHead(404, ) res.write('404 Not Found') res.end() return > // В противном случае отправим ответ со статусом 200 OK, // и добавляем правильный заголовок типа контента res.writeHead(200, ) // Считать файл и передать его в ответ const fileStream = fs.createReadStream(filePath) fileStream.pipe(res) >)

Создание HTTP-сервера с фреймворками Node.js

Фреймворки Node.js, такие как Express, Koa.js и Hapi.js, поставляются с различными полезными функциями промежуточного программного обеспечения, в дополнение к множеству других удобных функций, которые избавляют разработчиков от необходимости писать самим.

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

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

const express = require('express') const app = express() // Укажем директорию в которой будут лежать наши файлы app.use(express.static('public')) // Отправляем index.html, когда пользователи получают доступ к // корневому каталог с использованием res.sendFile() app.get('/', (req, res) => < res.sendFile(__dirname + '/public/index.html') >) app.listen(5000)

Koa.js не имеет подобного плагина внутри своего ядра, поэтому любой требуемый плагин должен быть установлен отдельно. Последняя версия Koa.js использует асинхронные функции в пользу обратных вызовов. Для обслуживания статических файлов вы можете использовать плагин koa-static .

const serve = require('koa-static') const koa = require('koa') const app = new koa() // Укажем директорию в которой будут лежать наши файлы // По умолчанию koa-static будет обслуживать файл index.html в корневом каталоге app.use(serve(__dirname + '/public')) app.listen(5000)

Hapi.js поддерживает настройку и вращается вокруг настройки объекта server . Он использует плагины для расширения возможностей, таких как маршрутизация, аутентификация и так далее. Для обслуживания статических файлов нам понадобится плагин с именем inert .

const path = require('path') const hapi = require('hapi') const inert = require('inert') // Маршруты могут быть настроены на объекте сервера const server = new hapi.Server( < port: 5000, routes: < files: < relativeTo: path.join(__dirname, 'public') >> >) const init = async () => < // server.register() команда добавляет плагин в приложение await server.register(inert) // inert добавляет обработчик каталога в // указатель маршрута для обслуживания нескольких файлов server.route(< method: 'GET', path: '/', handler: < directory: < path: '.', redirectToSlash: true, index: true >> >) await server.start() > init()

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

Завершение

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

  • HTTP by MDN
  • Anatomy of an HTTP Transaction
  • HTTP Server: Everything you need to know to build a simple HTTP server from scratch
  • nodejs
  • node.js
  • перевод с английского

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *