ProgIngContrSystems

Матеріали дисципліни "Програмна інженерія в системах управління"

Програмна інженерія в системах управління. Лекції. Автор і лектор: Олександр Пупена

<- до лекцій на основну сторінку курсу
   

4. Основи HTTP

4.1. Протокол HTTP

HTTP (HyperText Transfer Protocol — «протокол передачі гіпертексту») — протокол прикладного рівня передачі даних, який є повінстю текстовим, тобто використовуються тільки літери та цифри. Початково проткол використовувався для передачі гіпертекстових документів HTML, зараз використовується для передачі чого завгодно.

У обміні приймають участь два застосунки (рис.4.1):

  • HTTP Клієнт (наприклад Web Browser) - ініціатор, той застосунок, якому потрібні ресурси серверу. Він формує запит (Request Message) на сервер на виконання операціъ з ресурсом.
  • HTTP Сервер (Web Server) - той застосунок, у якого є ресурси. Він обробляє запит клієнта і відправляє відповідь (Response Message), у якому повертає результат обробки ресурсу, або сам ресурс.

рис.4.1. Клієнт-серверний обмін в HTTP.

На сьогодні інсує кілька версій: HTTP/1.1, впроваджується HTTP/2 (з 2015) та HTTP/3 (з 2019).

HTTP так само і багато споріднених протоколів використовує стандартний стек TCP, UDP, IP та інші (рис.4.2)

рис.4.2. Стек протоколів HTTP

Розглянемо приниципи функціонування HTTP на прикладі (рис.4.3).

1) Коли користувач заходить за посиланням на WEB-ресурс він вказує URL того ресурсу (наприклад сторінки), який необхідно завантажити.

2) Браузер запитує цей ресурс за допомогою повідомлення в текстовому форматі, що починається з назви методу GET в якому передається адреса ресурсу та додаткові параметри запиту. Це повідомлення передається по TCP до серверу по вказаному порту. Якщо користувач не вказав порт він буде рівним 80 (див. попередню лекцію).

рис.4.3. Приклад фунуціонування протоколу HTTP.

3) Сервер, отримавши повідомлення на отримання ресурсу, шукає його за URL.

4) У випадку знаходження ресурсу сервер відправляє відповідь, в заголовку якої вказує позитивний результат виконання запиту 200 Ok. Також в корисному навантаженні він передає запрошуваний ресурс.

5) Браузер виводить ресурс, якщо це буде HTML-сторінка показує її у відповідному вигляді.

Ідентифікація ресурсу

Ресурси на сервері - це документи у різному форматі, які можна отримати, записати, змінити і т.п. Для доступу до потрібного ресурсу вказується його унікальний для серверу ідентифікатор розміщення - URL (Uniform Resource Locator). Він задається у вигялді рядку і має наступний формат:

<схема>://<логін>:<пароль>@<хост>:<порт>/<шлях>?<параметри>#<якір>
  • схема – це означення того, який проткол використовується для доступу ресурсу, наприклад http або https
  • логін та пароль – це ім’я і пароль користувача, якщо доступ до ресурсу обмежений; як видно вони розділені двокрапкою; якщо дсотуп до ресурсу не обмежується, логін та пароль не вказуються
  • хост - доменне ім’я хоста (DNS) або IP-адреса
  • порт – TCP порт хоста, якщо не вказується,
  • шлях – інформація що уточнює місцезнаходження ресурсу
  • параметри – рядок запиту з параметрами, що передаються на сервер (методом GET)
    • використовується разділювач параметрів — знак &.
  • #<якір> - якір, тобто заголовок всередині документа, або атрибут id

Приклади:

https://uk.wikipedia.org/wiki/Уніфікований_локатор_ресурсів#Cтруктура http://asu.in.ua/viewtopic.php?p=6135#p6135

Структура повідомлення

Як зазначалося в протоколі HTTP повідомлення-запит та повідомлення-відповідь мають повністю текстовий формат. Повідомлення складається з (рис.5):

  • стартового рядку, який завершується символом кінця рядку і включає в себе
    • для запиту вказується рядок запиту (request line): у ньому вказується метод (на рисунку GET), ресурс (на рисунку /doc/test.html) та версія протоколу (на рисунку HTTP/1.1)
    • для відповіді вказується статусний рядок (status line): у ньому вказується версія протоколу (на рисунку HTTP/1.1), код статусу (на рисунку 200) та текстове представлення статусу (на рисунку OK)
  • headers (заголовки), які уточнюють повідомлення; кожен заголовок закінчується символом кінця рядку; є тільки один обовязковий заголовок для клієнта - Host, в якому треба вказати імя хоста, до якого відбувається звернення; усі інші заголовки добалвяються за необхідності;
  • body (тіло повідомлення), яке включає зміст ресурсу; може бути порожнім, наприклад у повідомленні-запиті на отримання ресурсу
  • розділювач - пустий рядок, який розділяє заголовки і тіло повідомлення

рис.4.4. Структура повідомлення HTTP

Перевірити роботу http можна за допомогою програми-терміналу, наприклад для систем Windows це PuTTY (рис.4.5). Для цього треба підключитися до потрібного порта потрібного host в режимі передачі тексту (raw). Далі у консольному вікні набрати текстове повідомлення, після подвійного Enter з’явиться відповідь від серверу.

рис.4.5. Приклад перевірки роботи HTTP за допомогою PuTTY.

Методи запитів

Метод запиту (HTTP Method) - це означення дії, яку необхідно провести над ресурсом. За великим рахунком це може бути довільний символьний набір, але цей метод повинен підтримуватися і Client і Server. Тим не менше є стандартні методи, зокрема:

  • GET – запит на зміст ресурсу
  • POST – передача даних для існуючого ресурсу
  • HEAD – запит інформації про ресурс але без змісту
  • PUT – розміщення нового ресурсу на Web-сервері
  • PATCH – часткова зміна ресурсу
  • DELETE – видалення ресурсу з Web-серверу
  • TRACE – трасировка (ехо-запит) перевірки зміни запиту по шляху
  • OPTIONS – запит підтримуваних методів HTTP та розширень
  • CONNECT – підключення до Web-серверу через проксі

Статуси відповідей

Статус відповіді вказує на результат виконання сервером запиту. Він включає числове представлення у вигялді коду та текстову рошифровку. Перша цифра тризначного коду (сотні) вказують на тип відповіді:

  • 1XX – інформаційна; наприклад 101 switching protocols вказує на те, що відбулося переключення на інший протокол (наприклад з HTTP на WebSocket)
  • 2XX – успішне виконання; наприклад 200 ОК
  • 3ХХ – перенаправлення на інше розміщення ресурсу; наприклад 301 – перенаправлення на постійне розміщення, 307 – перенаправлення на тимчасове переміщення
  • 4ХХ – помилка з причини клієнта; наприклад 403 –доступ заборонений за неправильної вказівки користувача та пароля, 404 – ресурс не знайдено за вказаним посиланням
  • 5ХХ – помилка на сервері; наприклад 500 – відбулася внутрішня помилка серверу

Заголовки

Заголовки HTTP (HTTP Headers) уточнюють повідомлення. Описуються парою ім'я: значення (див. рис.4.6). Наприклад

Content-Type: text/html;charset=utf-8

задає формат і спосіб представлення тіла повідомлення типу text/html з кодуванням charset=utf-8.

Існують стандартні заголовки, які описані в документах RFC. Нестандартні заголовки повинні починатися з X-. Для протоколу HTTP > v1.1 заголовок «Host» в повідомленні-запиті повинен бути обов’язковим, так як на одному IP/домені може бути декілька Веб-серверів. Список заголовків можна подивитися на Вікіпедії.

Розглянемо вплив заголовку Connection на функціонування обміну. Заголовок вказує на властивість підключення, зокрема Connection: Keep-Alive вказує на необхідність утримання (persistent) з’єднання після відповіді на запит. У протоколі HTTP/1.0 передбачалося, що після обробки кожного запиту – з’єднання розривається. Однак для багатьох випадків це може спричинити до значних часових затрат. Розглянемо це на прикладі (рис.7). Якщо при завантаженні сторінки необхідно додатково зробити запит, наприклад, на завантаження рисунків для неї, то в звичайному варіанті після кожного запиту GET TCP-з’єднання в HTTP/1.0 буде розриватися, хоча логічний сеанс обміну при цьому триває. Як відомо з попередньої лекції це приведе до додаткових часових затрат, тому для утримання з’єднання в HTTP/1.0 потрібен заголовок Connection: Keep-Alive, який після відповіді серверу тримає TCP-з’єднання активним протягом 5-15 секунд (залежить від реалізації серверу). У версії HTTP/1.1 за замовченням вважається даний параметр persistent а у 2-й версії заголовок взагалі заборонений.

рис.4.6. Функціонування постійного з’єднання Persisten Connection

Інший прикладом є використання заголовку Cache-Control. Для прискорення обміну завантажувані ресурси можуть кешуватися, тобто зберігатися на локальних (приватних) або проміжних загальнодоступних (shared) кешах (рис.8). Тобто якщо запит проходить через сервера, які передбачають кешування, може повернутися старе значення ресурсу. Це з одного боку зменшує трафік, так як надає багатьом клієнтам швидше доступ до одного і того ж ресурсу. З іншого боку, якщо ресурс (наприклад сторінка) змінився, усі клієнти отримають старе значення. Для вказівки параметрів роботи з кешем передбачений заголовок: Cashe Control, наприклад:

  • Cache-Control: no-cache, no-store - не кешувати, не зберігати,
  • Cache-Control: max-age=31536000 - максимальний час збереження в кеші в секундах

4.2. Робота з HTTP в Node-RED

У Node-RED є вузли для роботи як з клієнтськими запитами так і для реалізації серверної обробки.

HTTP requests (робота з клієнтськими запитами)

Відправляє запити HTTP і повертає відповідь на нього (рис.9). В якості вхідного значення приймає наступні властивості повідомлень:

  • url (string) – якщо не сконфігуроване у вузлі, ця опціональна властивість виставляє url для запиту.
  • method (string) - якщо не сконфігуроване у вузлі, ця опціональна властивість виставляє метод HTTP для запиту. Повинно бути GET, PUT, POST, PATCH бо DELETE.
  • headers (object) – виставляє HTTP заголовки в запиті
  • cookies (object) – якщо вказані, можуть бути використані для відправки куків з запитом
  • payload – виставляє тіло для запиту
  • rejectUnauthorized – якщо виставлено в false дозволяє робити запити на сайти https, які використовують сертифікати, які підписуються самостійно
  • followRedirects – якщо виставлено в false запобігає наступним перенаправленням (HTTP 301). true за замовчуванням

рис.4.7. Налаштування вузлу HTTP requests

На виході формує:

  • payload (string object buffer) – тіло відповіді. Вузол може бути налаштований так, щоб повернути тіло у вигляді string, спробувати розпарсити його як рядок JSON або залишити його у вигляді двійкового буфера.
  • statusCode (number) - код стану відповіді або код помилки, якщо запит не може бути завершений.
  • headers (object) – об’єкт, що містить заголовки відповідей
  • responseUrl (string) - у випадку, якщо під час обробки запиту відбулися будь-які перенаправлення, це властивість є останньою адресою, що переадресовується. В іншому випадку це URL оригінального запиту.
  • responseCookies (object) - якщо відповідь включає файли cookie, ця властивість є об’єктом пар імені/значення для кожного cookie.

Якщо сконфігуровано у вузлі, властивість URL може містити теги mustache-style. Вони дозволяють створювати URL, використовуючи значення вхідного повідомлення. Наприклад, якщо URL-адресу встановлено example.com/} в це місце буде автоматично додано msg.topic. Використання потрійних фігурних дужок } запобігає вилученню mustache із символів на зразок /& і т.д.

Примітка: Якщо запускається за проксі-сервері, необхідно встановити стандартну змінну середовища http_proxy=... і перезапустити Node-RED, або використовувати вузол Proxy Configuration. Якщо було встановлено вузол Proxy Configuration, конфігурація цього вузлу має перевагу перед змінною середовища.

Для того щоб використовувати більше одного з таких вузлів в тому самому потоці, необхідно дотримуватися властивості msg.headers. Перший вузол встановить цю властивість з заголовками відповіді. Тоді наступний вузол буде використовувати ці заголовки для свого запиту - це звичайно не правильно. Якщо властивість msg.headers залишається незмінною між вузлами, вона буде ігноруватися другим вузлом. Щоб встановити користувальницькі заголовки, msg.headers слід спочатку видалити або скинути порожнім об’єктом: {}.

Властивість cookies, передана вузлу, повинна бути об’єктом з парою ім’я : значення. Значення для встановлення значення cookie може бути string, або об’єктом з єдиною властивістю value. Будь-які файли cookie, повернені запитом, передаються назад у властивості responseCookies.

Для виконання запиту завантаження файлу, msg.headers["content-type"] слід встановити на multipart/form-data , а msg.payload , переданий у вузол, повинен бути об’єктом із такою структурою:

{
    "KEY": {
        "value": FILE_CONTENTS,
        "options": {
            "filename": "FILENAME"
        }
    }
}

Значення KEY, FILE_CONTENTS та FILENAME слід встановити у відповідні значення.

Якщо msg.payload є Object, вузол буде автоматично встановлювати тип контенту запиту в application/json і кодувати тіло відповідним чином.

Для кодування запиту як форми даних msg.headers["content-type"] буде встановлюватися як application/x-www-form-urlencoded.

На рис.4.8 показаний приклад з вузлом HTTP requests

рис.4.8. Приклад використання HTTP requests

Http in (вхідне повідомлення HTTP-серверу)

Створює точку для з`єднання HTTP для створення веб-служб (рис.4.9).

рис.4.9. Налаштування Http in

На виході формує:

  • Payload (object) - Для запиту GET містить об’єкт з параметрами рядка запиту. В іншому випадку, містить тіло запиту HTTP.
  • req (object) - Об’єкт запиту HTTP. Цей об’єкт містить кілька властивостей, які надають інформацію про запит.

Вузол прослуховує конфігурований шлях для запитів певного типу. Шлях може бути повністю означений, наприклад /user, або включати іменовані параметри, які приймають будь-яке значення, наприклад /user/:name. Коли використовуються іменовані параметри, їх фактичне значення в запиті може бути доступне за посиланнями msg.req.params. Для запитів, які включають тіло, наприклад POST або PUT, вміст запиту доступний як msg.payload.

Якщо тип вмісту запиту може бути визначений, тіло буде проаналізовано до будь-якого відповідного типу. Наприклад, application/json буде парсений до його представлення в об’єкти JavaScript.

Примітка: цей вузол не надсилає відповіді на запит. Потік повинен містити вузол HTTP Response для завершення запиту.

Http response (вихідне повідомлення HTTP-серверу)

Надсилає відповіді на запити, отримані від вузла HTTP In (рис.4.10).

рис.4.10. Налаштування Http response

В якості вхідного значення приймає наступні властивості повідомлень:

  • payload (string) – тіло відповіді
  • statusCode (number) – якщо встановлений, використовується в якості статусного коду відповіді. За замовченням 200
  • headers (object) – заголовки, якщо встановлений забезпечує HTTP заголовки, які включаються у відповідь
  • cookies (object) – якщо встановлений, може бути використаний для встановлення або видалення куків (cookies)

statusCode і headers також можуть бути встановлені в налаштуваннях самого вузла. У цьому випадку їх не можна перевизначити відповідними властивостями повідомлення.

Властивість cookies повинна бути об’єктом пар імен/значень. Значення може бути або рядком для встановлення значення куки з параметрами за замовчуванням, або це може бути об’єктом опцій.

Наступний приклад встановлює два файли cookies - один з них називається name зі значенням nick, інший називається session зі значенням 1234 з терміном дії 15 хвилин.

msg.cookies = {
    name: 'nick',
    session: {
        value: '1234',
        maxAge: 900000
    }
}

Допустимі опції:

  • domain - (String) ім’я домену для куки
  • expires - (Date) термін дії в GMT. Якщо не вказано або встановлено на 0, створює сеансовий cookie
  • maxAge - (String) термін дії відносно поточного часу в мілісекундах
  • path - (String) шлях куки, за замовченням /
  • value - (String) значення для куки

Для видалення, куки встановлюється в null

На рис.4.11 показаний приклад використання вузлів http in/out в парі. Коли відбувається запит на сторінку hello видається текстовий зміст.

рис.4.11. Приклад використання http in/out

4.3. Робота зі змістом HTML повідомлень

Тип змісту тіла повідомлення (Content-Type)

Хоч протокол HTTP повністю текстовий, за допомогою тексту можна кодувати будь-який зміст тіла, навіть бінарні файли. Однак для їх правильної інтерпретації необхідно вказати тип змісту за допомогою заголовка Content-Type. Заголовок може включати декілька директив, розділені крапкою з комою:

  • media-type, тип змісту, наприклад text/html, або multipart - для вказівки багато-частинних повідомлень
  • charset – стандарт кодування, наприклад utf-8
  • boundary – для багато-частинних (multipart) повідомлень розділювач

Наприклад:

Content-Type: text/html; charset=utf-8 
Content-Type: multipart/form-data; boundary=something

Тип змісту, визначається типом MIME(Multipurpose Internet Mail Extensions) – стандарт на характер і формат документу, файлу або даних. Він описується парою тип/підтип, тобто:

type/subtype

Ці типи можуть бути дискретними, тобто які описують весь формат, або у випадку змішаного формату (наприклад текст та рисунки) включати кілька частин. Популярні дискретні формати

application/octet-stream (бінарний)
text/plain (текстовий)
text/css, text/html, text/javascript, text/xml (текстовий з ромзіткою)
image/gif, image/jpeg, image/png (зображення)
application/json (JSON)

Інші дискретні формати:

text/css, audio/mpeg, audio/ogg, audio/*, video/mp4, application/*, pplication/ecmascript
application/octet-stream ...

Для змісту що включає кілька розділів (зміст) виділяється тип MIME Multipart. На рис.4.12 показаний приклад використання змісту, який включає кілька розділів. Це тіло повідомлення відправлення HTML-форми. Для цього використовується директива multipart/form-data заголовку Content Type . Директиваboundary вказує на роздільник, який використовується для ідентифікації початку частин. Далі кожен розділ тіла повідомлення починається з вказаного роздільника, після чого вказується тип формату через Content-type .

рис.4.12. Приклад використання MIME Multipart

Вузол HTML

Витягує елементи з HTML-документа, що міститься в msg.payload за допомогою селекторів CSS (рис.4.13).

В якості вхідного значення приймає наступні властивості повідомлень:

  • payload (string) – html- рядок з якого вилучаються елементи.
  • select (string) - селектор, може бути використане це значення властивості msg, якщо воно не налаштовано на панелі редагування.

рис.4.13. Налаштування вузлу HTML

На виході формує:

  • payload (array string) - результатом може бути одне повідомлення з корисним навантаженням, що містить масив відповідних елементів, або кілька повідомлень, кожен з яких містить відповідний елемент.
  • Якщо надсилаються декілька повідомлень, вони також мають набір parts.

Цей вузол підтримує комбінацію селекторів CSS і jQuery. Докладніше про підтримуваний синтаксис див. за цим посиланням або Документацію css-select.

На рис.4.14 наведений приклад використання HTML-парсера. Вузол http request робить запит на сторінку з сайту example.org використовуючи метод get. Сторінка завантажується в Payload як текстове повідомлення. Далі повідомлення проходить через вузол парсера body, який витягує html-зміст усіх html-тегів body та відправляє їх окремими повідомленнями в payload. Враховуючи, щ вузол body в html-документі тільки один, його зміст виводиться один раз на панелі налагодження. Корисне навантаження цього повідомлення переходить через інший html-парсер з іменем p де вилучаються усі абзаци (тег p) і відправляються як масив повідомлень в форматі html.

рис.4.14. Приклад використання HTML-парсера

Вузол Template

Вузол Template може використовуватися для створення текстового значення за допомогою означеного шаблону та властивостей повідомлення, які вказуються в конкретних полях. Для формування результату він використовує шаблонну мову Mustache, у якій поля-замінники в шаблоні виділяються подвійними фігурними дужками. Наприклад, шаблон:

This is the payload: !

замінить `` з значенням властивості повідомлення payload.

На рис.4.15 показано приклад налаштування вузла Template. Налаштування Property вказує на те, яка саме властивість буде змінюватися даним вузлом на виході. У якості шаблону можна задавати статичний шаблон, який записаний у полі Template, або передати його через властивість msg.template. У останньому випадку необхідно щоб поле Template в конфігурації вузла було порожнім. Можна вибирати різний синтаксис підсвічування в залежності від призначення виходу.

рис.4.15. Налаштування вузла Template

На рис.4.16 показаний простий приклад використання вузла Template.

рис.4.16. Простий приклад використання вузла Template

Для формування замінників в шаблоні окрім властивостей повідомлення можна використовувати значення контекстів. Це може бути як контекст за замовченням або, так і іменоване сховище для контексту або.

За замовчуванням, Mustache замінить певні символи своїми HTML-кодами. Щоб зупинити це, треба скористатися потрійними фігурними дужками: }. На рис.4.17 показаний приклад, у якому для формування змісту у форматі html використовуються обидва варіанти – з подвійним і з потрійними дужками. Шаблони для обидвох вузлів зроблені у форматі html, який включає тег тіла, що у свою чергу включає замінник msg.payload. На їх вхід подається значення у форматі html. У першому варіанті (верхній вузол) символи що використовуються у форматуванні html замінені на їх кодові представлення (спецсимволи). Це робиться тому, що подвійні дужки вказують на те, що зміст має бути представлений як текст, а не як html. Тому відбувається перетворення, щоб зберегти відображення спецсимволів на кшталт “<” , “/”, “>” у тому ж вигляді. При потрійних дужках ніякого попереднього перетворення не робиться, тому увесь зміст зрештою буде інтерпретуватися як html.

рис.4.17. Приклад використання потрійних фігурних дужок.

Mustache за допомогою секцій підтримують прості цикли у списках. Наприклад, якщо msg.payload містить масив імен, таких як: ["Nick", "Dave", "Claire"], то шаблон типу:

<ul>

 <li></li>

</ul>

створить список HTML імен:

<ul>
 <li>Nick</li>
 <li>Dave</li>
 <li>Claire</li>
</ul>

Додатково про форматування Mustache можна ознайомитися за посиланням. Якщо шаблон генерує валідний вміст JSON або YAML, його можна налаштувати для аналізу результату на відповідний об’єкт JavaScript.

Питання для самоперевірки.

  1. Розкажіть про загальні принципи функціонування протоколу HTTP.
  2. На якому протоколі транспортного рівня базується HTTP?
  3. Поясніть що таке ресурс HTTP? Як він ідентифікується на сервері?
  4. Розкажіть про структуру повідомлення HTTP.
  5. Розкажіть про призначення методів запитів HTTP.
  6. Розкажіть про призначення статусів відповіді HTTP.
  7. Розкажіть про призначення заголовків HTTP.
  8. Розкажіть про призначення кешування в HTTP. Як можна керувати кешем в протоколі HTTP?
  9. Як реалізована робота клієнта HTTP в Node-RED?
  10. Як реалізована робота HTTP-сервера в Node-RED?
  11. Як вказується формат повідомлення в HTTP?
  12. Що таке Multipart повідомлення?
  13. Рокзажіть про роботу вузла HTML-парсера в Node-RED.
  14. Рокзажіть про роботу вузла Template в Node-RED.
<- до лекцій на основну сторінку курсу