Веб сервер на JavaScript
Уже давно есть возможность написать свой сервер, с нуля на JavaScript, с использованием Node.js движка от браузера Chrome.
В первом моем посте-заметке на хабре, хочу поделиться своим опитом создания самописного сервера.
Так ка я люблю хардкор в програмировании, то когда необходимо било сделать сайт, я решил делать всю серверную часть с нуля! Почему я вибрал JavaScript? — дело в том что мне также необходимо било запрограмировать и сам сайт (странички хтмл). И как Вы догадались, и там и там один и тот же язык — JavaScript, что несомненно является плюсом для разработчика, так как не надо изучать и понимать десять разных синтаксесов и парадигм языков.
Веб сервер в две строки кода
Напишем пару строчек кода и создадим собственный веб сервер, назовем файл index.js.
var http = require(‘http’);
http.createServer(function (req, res) res.end(‘Hello World\n’);
>).listen(80, ‘localhost’);
console.log(‘Server running at localhost’);
Поясню, сначала подключаем модуль http для собственно веб сервера, далее создаем асинхронную функцию калбек для входящих запросов и на конец то стартуем сервер на 80 порту. Очень просто и все понятно, нет ничего лишнего.
Важно помнить, что Skype может висеть на 80 порту, по этому необходимо убить Skype перед запуском сервера!
Запускаем сервер, с консоли, следующим образом:
Вот и все, переходим в браузер и вводим localhost, в ответ получим Hello World!
Ето только вершина айсберга, в следующих заметках я расскажу более детально как сделать полноценный веб сервер для большого сайта.
Спасибо за внимание!
#7 – Создание своего сервера Node JS

На основе лишь одного Node JS вы легко можете создать свой сервер. Такой сервер может работать с пользователем, отслеживать URL адреса и показывать пользователю разные страницы сайта.
Видеоурок
Благодаря модулю http можно создавать и подключаться к серверу буквально за пару строчек кода. В ходе урока мы создали локальный сервер, на котором вывели текст без использования HTML-тегов .
Для создания сервера необходимо подключиться к модулю http и использовать метод createServer . В метод необходимо поместить функцию с двумя параметрами: request (запрос) и response (ответ).
В параметре response мы можем установить какие заголовки должен вернуть сервер, а также что должно быть отображено на странице сайта.
В заголовках мы указываем типы данных, которые мы хотим передать и отобразить на сайте. В данный момент мы работаем с простым типом данных, а именно с обычным текстом — text/plain . При работе с заголовками важно указать кодировку, чтобы текст написанный на кириллице выводился корректно.
Для вывода информации в браузере используйте метод end :
const http = require('http') // Необходимый модуль // Создание сервера const server = http.createServer((req, res) => < // Указание заголовков (тип данных и кодировка) res.writeHead(200, ) // Текст, который будет отображен на странице res.end('Просто обычный текст без HTML') >)
Также необходимо установить само соединение, в котором указать порт, а также адрес сервера. В нашем случае мы используем локальные параметры:
// server - переменная созданная ранее server.listen(3000, '127.0.0.1')
Если запустить программу и зайти на адрес 127.0.0.1:3000 , то на сайте будет надпись: «Просто обычный текст без HTML».
Сервер
Для работы с сервером и протоколом http в Node.js используется модуль http.
Чтобы создать сервер, следует вызвать метод http.createServer() :
const http = require("http"); const server = http.createServer();
Метод createServer() возвращает объект http.Server . Для обработки подключений в метод createServer передается функция-обработчик:
const http = require("http"); const server = http.createServer(function(request, response)< response.end("Hello METANIT.COM!"); >);
Эта функция принимает два параметра:
- request : хранит информацию о запросе
- response : управляет отправкой ответа
В примере выше с помощью метода response.end() в ответ клиенту посылается строка «Hello METANIT.COM!».
Но чтобы сервер мог прослушивать и обрабатывать входящие подключения, у объекта сервера необходимо вызвать метод listen() . Данный метод может принимать различный набор параметров. Но обычно в качестве первого параметра передается номер порта, по которому запускается сервер.
const http = require("http"); const server = http.createServer(function(request, response)< response.end("Hello METANIT.COM!"); >); server.listen(3000);
В данном случае сервер запускается по адресу 3000. Также дополнительно можно передать в метод listen функцию, которая будет срабатывать при запуске сервера:
const http = require("http"); const server = http.createServer(function(request, response)< response.end("Hello METANIT.COM!"); >); server.listen(3000, function()< console.log("Сервер запущен по адресу http://localhost:3000")>);
Например, запустим приложение, и после успешного запуска мы увидим на консоли соответствующее сообщение:
c:\app> node app.js Сервер запущен по адресу http://localhost:3000
Поскольку сервер запущен на порту 3000, то мы можем обратиться к нашему приложению в браузере по адресу http://localhost: 3000

Request
Параметр request позволяет получить информацию о запросе и представляет объект http.IncomingMessage . Отметим некоторые основные свойства этого объекта:
- headers : возвращает заголовки запроса
- method : тип запроса (GET, POST, DELETE, PUT)
- url : представляет запрошенный адрес
Например, определим следующий файл app.js:
const 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, function()< console.log("Сервер запущен по адресу http://localhost:3000")>);
Запустим его и обратимся в браузере по адресу http://localhost:3000/ , и консоль выведет нам информацию о запросе:
c:\app> Сервер запущен по адресу http://localhost:3000 Url: / Тип запроса: GET User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Все заголовки < host: 'localhost:3000', connection: 'keep-alive', 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"macOS"', 'upgrade-insecure-requests': '1', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', 'sec-purpose': 'prefetch;prerender', purpose: 'prefetch', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 'sec-fetch-site': 'none', 'sec-fetch-mode': 'navigate', 'sec-fetch-user': '?1', 'sec-fetch-dest': 'document', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,fr;q=0.6,de;q=0.5,tr;q=0.4,zh-CN;q=0.3,zh;q=0.2,bg;q=0.1' >
Response
Параметр response управляет отправкой ответа и представляет объект http.ServerResponse . Среди его функциональности можно выделить следующие методы:
- statusCode : устанавливает статусный код ответа
- statusMessage : устанавливает сообщение, отправляемое вместе со статусным кодом
- setHeader(name, value) : добавляет в ответ один заголовок
- write : пишет в поток ответа некоторое содержимое
- writeHead : добавляет в ответ статусный код и набор заголовков
- end : сигнализирует серверу, что заголовки и тело ответа установлены, в итоге ответ отсылается клиента. Данный метод должен вызываться в каждом запросе.
В общем случае для отправки ответа достаточно вызвать метод end() , в который передаются отправляемые данные:
response.end("Hello METANIT.COM!");
С помощью метода write() можно кусками добавить данные в ответ. Например, изменим файл app.js следующим образом:
const http = require("http"); http.createServer(function(request, response)< response.write("Text 1\n"); response.write("Text 2\n"); response.end("End"); >).listen(3000, function()< console.log("Сервер запущен по адресу http://localhost:3000")>);
Запустим файл и обратимся в браузере к приложению:

Можно через end() ничего не добавлять в ответ, но в любом случае этот метод следует вызывать при отправке ответа:
const http = require("http"); http.createServer(function(_, response)< response.write("Text 1\n"); response.write("Text 2\n"); response.end(); >).listen(3000, function()< console.log("Сервер запущен по адресу http://localhost:3000")>);
Отправка заголовков
Метод setHeader() позволяет установить заголовки ответа:
const http = require("http"); http.createServer(function(_, response)< response.setHeader("UserId", 12); // установка кастомного заголовка response.setHeader("Content-Type", "text/html; charset=utf-8;"); response.write("Привет мир
"); response.end(); >).listen(3000, function()< console.log("Сервер запущен по адресу http://localhost:3000")>);
В данном случае для теста устанавливаем кастомный заголовок «UserId», пусть он равен 12. А чтобы отправляемый ответ интерпретировался браузером как код html, для заголовка «Content-Type» устанавливаем значение «text/html; charset=utf-8;». Результат работы:

Маршрутизация
По умолчанию 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, например, 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.