README
X.WWW.SERVER.11
- Подготовка к работе : preparing for work
- Начало работы : the beginning of the work
- Запрос и ответ : request and response
- SSL сертификаты : SSL certificates
preparing for work
Добро пожаловать в модуль x.web.server.11
installation
Установить модуль можно с помощью утилиты командной строки: npm i x.web.server.11
merger
Для создания нового проекта следует: воспользоваться утилитой модуля x.web.server.11
- merger
, создать новую директорию для будущего проекта, перейти в неё, в командной строке запустить среду nodejs
, и выполнить следующий сценарий:
require('x.web.server.11').merger();
test run
Для пробного запуска сервера следует в коренной директории проекта, в командной строке, выполнить nodejs ucodehere.js
. Проверить его работу можно открыв тестовую страницу в браузере: http://localhost:8080/html/index.html
the beginning of the work
В коренную директорию проекта, утилитой merger
, я перенес файл ucodehere.js
, который содержит в себе пример конструкции веб-сервера, модуля x.web.server.11
module x.web.server.11
Методом модуля x.web.server.11
create
сервер формирует свою конфигурацию из двух переменных: pathToConfigDirectories
- путь к директории файлов конфигурации; и nameOfTheMainConfigurationFile
- имя основного, базового файла конфигурации.
// Путь к директории файлов конфигурации
let pathToConfigDirectories = '/nsj/prjct/config';
// Имя основного, базового файла конфигурации
let nameOfTheMainConfigurationFile = 'main.json';
let x = require('x.web.server.11')
.create(pathToConfigDirectories
,nameOfTheMainConfigurationFile);
x.www((server)=>{
/*Функция серверных событий*/
}, (request, response)=>{
/*Функция ответов и запросов*/
});
server events
Функция серверных событий, в объекте модуля, предусмотрена для объявления сценариев, которыми будут обработаны серверные события. Так как server
- объект, наследующий класса EventEmiter
, то и сценарии в нём назначаются функцией on
x.www((server)=>{
server.on('request', (request, response)=>{
console.log('Сработало серверное событие "request"')
});
}, (request, response)=>{
/*Функция ответов и запросов*/
});
custom events
В объекте модуля предусмотрена функция запросов и ответов для обработки и завершения запросов к серверу извне. Внутри тела функции доступны два объекта - request
и response
модулей http
и https
, которые наследуют класс EventEmiter
- описаные в официальной документации nodejs
.
x.www((server)=>{
/*Функция серверных событий*/
}, (request, response)=>{
console.log(`URL запроса: ${requset.url}`)
response.writeHead(200)
response.end()
});
configuration
В merger я передал путь к файлам конфигурации. Все скопированные в эту директорию файлы .json
считываются модулем при старте, и добавляются в общий пункт массива с именем config
- request.server.config
. Объект функции запросов и ответов веб-сервера request
. В качестве имени пункта в массиве request.server.config
используется имя файла без расширения .json
, например: содержимое файла с именем mysql.json
доступно в request.server.config.mysql
. Основной, базовый файл конфигурации, как правило, с названием main.json
, доступен в request.server.config
, а файлы, у которых названия имен совпадают с пунктами этого массива, будут перезаписывать его содержимое. Для названий файлов конфигурации лучше использовать уникальные значения, отличающиеся от имен пунктов, внутри основного файла конфигурации.
request and response
Обработка запросов и завершение ответов происходят: внутри тела функции запросов и ответов, сценариях ответов, и за счет исключений ответов из правил в методах объектов request
и response
request
Внутри тела функции запросов и ответов доступен объект request
из модулей http
и https
. Объект наследует класс EventEmiter
и подробно описан в документации nodejs
.
random values
Строка случайных символов алфавита, заданной длины: request.rav(3)
с результатом {text:'FyJ'}
uniform resource locator
Переменная request.variable.pathname
содержит в себе полный путь к запрошенному файлу: \nsj\prjct\srvr\html\index.html
Вывод функции parse
, встроенного модуля url
в nodejs
, содержится в каждом объекте request
в массив request.variable.parsed.url
{ protocol: 'http:',
slashes: true,
auth: null,
host: 'localhost:8080',
port: '8080',
hostname: 'localhost',
hash: null,
search: null,
query: [Object: null prototype] {},
pathname: '/html/index.html',
path: '/html/index.html',
href: 'http://localhost:8080/html/index.html' }
request headers
Переменная request.variable.parsed.header
содержит в себе перебранные заголовки запросов.
{ host: 'localhost:8080',
connection: 'keep-alive',
pragma: [Array],
'cache-control': [Array],
authorization: [Object],
'user-agent': [Array],
accept: [Array],
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'no-cors',
'sec-fetch-dest': 'image',
referer: [Url],
'accept-encoding': [Array],
'accept-language': [Array],
cookie: [Object] }
request data
Переменная request.variable.incomingData
содержит в себе буфер не перебранных входящих данных.
Переменная request.variable.parsed.incoming.data
содержит в себе перебранные входящие данные.
{ multipart:
[ { 'content-disposition': 'form-data',
name: 'x-textareat-name',
filename: null,
'content-type': null,
data:
<Buffer 40 43 41 41 3a 38 39 20 2d 20 40 3e 34 3d 3e 39 20 4f 37 4b 3a>,
mediatype: [] },
{ 'content-disposition': 'form-data',
name: 'x-file-name',
filename: 'квадрат.jpg',
'content-type': 'image/jpeg',
data:
<Buffer fd fd fd fd 00 10 4a 46 49 46 00 01 01 01 00 60 00 60 00 00 fd fd 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 ... >,
mediatype: [Array] } ],
urlencoded:
{ 'x-input-name': <Buffer d1 80 d1 83 d1 81 d1 81 d0 ba d0 b8 d0 b9>,
'x-textareat-name':
<Buffer d1 80 d1 83 d1 81 d1 81 d0 ba d0 b8 d0 b9 2b 2d 2b d1 80 d0 be d0 b4 d0 bd d0 be d0 b9 2b d1 8f d0 b7 d1 8b d0 ba>,
'x-select-name': <Buffer 78>,
'x-checkbox-name[y]': <Buffer 79>,
'x-radio-name': <Buffer 79> },
json: {"x-item-json":"x-value"} }
the write data request
Функция записи данных в файл, nodejs
модуля fs
, принимает четыре параметра: имя файла, данные, опции, функцию обратного вызова
let fs_module = require('fs');
fs_module.writeFile('./Полный путь к файлу.txt', 'Произвольный текст или буфер',{encoding: 'utf8'}, function (err) {
if(err) throw err;
console.log('write:', 'Запись завершена!');
});
response
Внутри тела функции запросов и ответов доступен объект response
из модулей http
и https
. Объект наследует класс EventEmiter
и подробно описан в документации nodejs
the caching response headers
В конфигурационном файле cache
есть возможность включить кэширующие заголовки директивой enable
в значении 1
. Директивой type
обозначены типы, ориентиры для кэширующих заголовков: extension
, file
и media
. Директивой headers
обозначены обязательные заголовки, и заголовки по умолчанию.
{
"enable":1,
"type":"extension",
"extension":[".css", ".js", ".ico", ".jpeg", ".jpg", ".html"],
"headers":{
"extension": {
".html": {"Cache-Control": "max-age=116"},
"default": {"Cache-Control": "max-age=121"}
}
}
}
the completion of the response
Союз request.pre[httpResponseCode].set(headers).end(data)
реализует завершение ответа сервера. Метод end
формирует тело ответа: либо из переданных в него данных; либо из переменной request.variable.compressed
; либо из request.variable.outgoing
. Метод set
формирует дополнительные заголовки ответа.
response.pre[200].set({
'Set-Cookie':'nave=value',
'Content-Type':'text/plain; charset=utf8'})
.end('Тело ответа!');
response data
Автономно прочитанные данные из файлов, для ответов сервера, содержатся в переменных request.variable.outgoing.data
и request.variable.compressed.data
; а медиатипы этих данных и метод сжатия – в request.variable.outgoing.mimetype
и request.variable.compressed.encoding
the reading of the response data
Функция чтения данных из файла, nodejs
модуля fs
, принимает два параметра: имя файла, и функцию обратного вызова.
let fs_module = require('fs');
fs_module.readFile('./srvr/tmp/квадрат.jpg', (err,data)=>{
if(err) throw err;
console.log(data);
})
media type of response data
Союз new request.media().ext({DATA:data})
определяет подходящее расширение файла с этими данными; new request.media().type({DATA:data})
определяет медиатип этих данными.
let fs_module = require('fs');
fs_module.readFile('./srvr/tmp/квадрат.jpg', (err,data)=>{
if(err) throw err;
console.log(new request.media().ext({DATA:data}));
console.log(new request.media().type({DATA:data}));
console.log(new request.media().ext({CONTENTTYPE:'image/jpeg'}));
console.log(new request.media().type({EXTENSION:'квадрат.jpg'.split('.').pop()}));
})
compression of the response data
Метод response.compress
осуществляет сжатие данных.
let fs_module = require('fs');
fs_module.readFile('./srvr/tmp/квадрат.jpg', (err,data)=>{
if(err) throw err;
response.compress(data, (encoding, data)=>{
console.log(request.variable.compressed.data
===data,encoding
, data)
})
});
response scenarios
Класс page
, объекта функции серверных событий server
образует союз server.page.set(hostnameArrayList, pathnameArrayList, functionArrayList)
и server.page.unset().[it(hostnameArrayList, pathnameArrayList, functionArrayList), not(hostnameArrayList, pathnameArrayList, functionArrayList), all()]
, добавляющие и удаляющие сценарии ответов.
adding response scenarios
Метод set
принимает три параметра: массив с именами хостов; массив с адресами страниц; массив с функциями сценария ответа.
x.www((server)=>{
function json_2 (request,response) {
response.pre[200].set({'Content-Type':'text/plain; charset=utf8'}).end('Сценарий завершения запроса отображен текстом в веб-странице!')
};
server.page.set( ['localhost'], ['/json_2'], [json_2]);
}, (request, response)=>{
/*Функция ответов и запросов*/
});
Запрос адреса /json_2
завершится выполнением функции json_2
.
removal response scenarios
Вызов метода unset
образует новый класс трёх методов: метод it
удаляет переданные сценарии; not
удаляет всё, кроме переданных сценариев; метод all
удаляет все добавленные сценарии.
x.www((server)=>{
server.page.unset().it(['localhost'],['/json_2'],['json_2']);
server.page.unset().not(['localhost'],['/json_2.html'],['json_2_html']);
server.page.unset().all()
}, (request,response)=>{
/*Функция ответов и запросов*/
});
exceptions
Когда я хочу продолжать обрабатывать запросы внутри функции запросов и ответов, несмотря на то, что ни запрошенный файл, ни сценарий ответа небыли найдены, я должен использовать директиву конфигурационного файла main.json
exception
вместе с правилами регулярных выражений.
"exception": ["/txt*"]
Все запросы с адресами, которые начинаются с /txt
, будут перенаправлены в функцию запросов и ответов для обработки и завершения ответа.
ssl certificates
Конфигурационный файл ssl
содержит директивы: dir.path.key
и dir.path.cert
– путь к директории с файлами сертификатов; file.name.key
и file.name.cert
– имена файлов с ключом и сертификатом; host
с перечнем хостов, чьи имена совпадают с именами директорий с файлами сертификатов; alias
– алиасы имен хостов.
{
"dir":{
"path":{
"key":"/nsj/prjct/ssl",
"cert":"/nsj/prjct/ssl"
}
},
"file":{
"name":{
"key":"server.key",
"cert":"server.crt"
}
},
"host":{
"name":["localhost"]
},
"alias": {
"localhost": ["www.localhost","127.0.0.1"]
}
}
Метод addSSLCert
, объекта server
, добавляет сертификаты внутри тела функции серверных событий.
x.www((server)=>{
server.on('addContext', (hosts)=>{
server.addSSLCert(hosts, (option)=>{
/*Путь с именем к файлу с ключом сертификата*/
option.key = server.config.ssl.dir.path.key
+'/'+option.hostname+'/'
+server.config.ssl.file.name.key
/*Путь с именем к файлу с сертификатом*/
option.cert = server.config.ssl.dir.path.key
+'/'+option.hostname+'/'
+server.config.ssl.file.name.key
option.alias =
server.config.ssl.alias
&&server.config.ssl.alias[option.hostname]
&&server.config.ssl.alias[option.hostname].length
?server.config.ssl.alias[option.hostname]
:undefined;
/*Для того чтобы изменения
вступили в силу, следует
вернуть объект option*/
return option;
});
});
/*Если в server есть addContext - это https соединение*/
if(server.addContext) {
/*Вызов функции addSSLCert методом emit объекта EventEmiter*/
server.emit('addContext', ['localhost']);
}
}, (request, response)=>{
/*Функция ответов и запросов*/
});