
Руководство по потокам TCP и HTTP: изменение HTTP-сообщений
24 февраля 2022 г.Представьте такую ситуацию: у нас есть HTTP-сервер и клиент, работающий с ним. Давайте подробнее заглянем под капот, что представляет собой процесс изменения HTTP-сообщений.
TCP-поток
Когда мы говорим о HTTP-серверах и клиентах, мы имеем в виду связь между сервером и клиентом путем отправки HTTP-сообщений между ними. Но для этого клиент и сервер должны сначала установить TCP-соединение. Давайте создадим экземпляр сервера и установим TCP-соединение. Мы будем использовать только утилиты от libuv, для понимания процесса под лупой.
В сетевой библиотеке есть специальный экземпляр Сервера. Давайте воспользуемся этим для создания экземпляра сервера и скажем ему прослушивать порт 3000 на хосте 0.0.0.0, который буквально называется localhost.
```javascript
константа сеть = требуется ('сеть');
константа HOST = '0.0.0.0';
постоянный ПОРТ = 3000;
постоянный сервер = новый net.Server();
server.listen(ПОРТ, ХОСТ);
Чтобы проверить, что все работает, мы можем добавить обработчики событий «подключения» и «прослушивания» или жизненных циклов сервера. Поскольку сервер наследует класс Emmiter, мы можем сделать это:
```javascript
server.on("прослушивание", () => {
console.log("сервер прослушивает");
server.on("соединение", () => {
console.log("соединение установлено");
Теперь вы можете установить TCP-соединение через порт 3000. Для этого воспользуемся telnet.
:::Информация
❯ телнет локальный хост 3000
Попытка ::1...
Подключен к локальному хосту.
Экранирующий символ '^]'.
Здорово. Соединение установлено. Теперь нам нужен способ чтения данных. Дело в том, что сеансы обмена сообщениями HTTP работают через сокеты TCP. Из документации Node.JS:
Мы можем получить к нему доступ при создании сервера.
```javascript
константа сеть = требуется ('сеть');
константа HOST = '0.0.0.0';
постоянный ПОРТ = 3000;
константный сервер = новый net.Server((сокет) => {
Итак, еще раз. Создаем сервер и просим его слушать порт 3000 локального хоста. Также мы попросили сокет, который обрабатывает этот порт, логировать полученные данные. Теперь мы можем добавить в сокет несколько обработчиков событий:
```javascript
socket.on("данные", (данные) => {
console.log(получить данные: ${данные}
);
Теперь мы снова можем подключиться к серверу и отправить сообщение.
:::Информация
❯ телнет локальный хост 3000
Попытка ::1...
Подключен к локальному хосту.
Экранирующий символ '^]'.
Привет
В консоли мы увидим это сообщение receive data: hello
.
На этом этапе важно понимать, что после установления TCP-соединения клиент и сервер могут взаимодействовать с помощью сокетов. Правильно, розетки появляются с обеих сторон.
Чтобы лучше понять это, вместо использования telnet давайте напишем клиент, используя сетевую библиотеку.
Вот код нашего сервера и клиента.
```javascript
константная сеть = требуется ("сеть");
константа HOST = "0.0.0.0";
постоянный ПОРТ = 3000;
константный сервер = новый net.Server((сокет) => {
socket.once("данные", (данные) => {
console.log(получить от клиента: "${data}"
);
socket.write("привет");
server.listen(ПОРТ, ХОСТ);
постоянный клиент = новый net.Socket();
client.connect(ПОРТ, ХОСТ);
client.write("привет");
client.on("данные", (данные) => {
console.log(получить с сервера: "${data}"
);
Веб-браузеры, такие как Google Chrome, по сути, являются одним и тем же клиентом, что и создает всю эту магию под капотом. Если вы запустите lsof -n -i TCP | grep Google
, вы увидите, сколько TCP-соединений установлено вашим браузером Chrome.
Еще одна важная вещь заключается в том, что к TCP-сокету этого сервера может быть подключено несколько клиентов.
Если клиенты устанавливают несколько TCP-подключений к серверу, клиентская ОС должна генерировать разные случайные исходные порты, чтобы сервер мог видеть их как уникальные подключения.
Разница между версиями HTTP
Стоит отметить разницу в заголовке Connection. В старой версии протокола для каждого обмена сообщениями устанавливалось отдельное соединение. Клиент запрашивает что-то с сервера, TCP-соединение установлено, клиент получает ответ, и соединение закрывается. В следующий раз клиенту нужно будет отправить еще один запрос на установление нового TCP-соединения. Не очень оптимально, правда? Вот почему был создан заголовок Connection. Если мы передаем keep-alive
с помощью Connection
, заголовок сообщит серверу, что не следует прерывать это соединение.
HTTP-поток
HTTP — это протокол прикладного уровня. Поток довольно прост:
- Вы вводите URL-адрес в браузере и нажимаете Enter
- Браузер ищет IP-адрес для домена
- Браузер инициирует TCP-соединение с сервером.
- Браузер отправляет HTTP-запрос на сервер
- Сервер обрабатывает запрос и отправляет ответ
- Браузер отображает контент
Что такое HTTP-сообщение?
Сообщения HTTP представляют собой простые линейные последовательности символов. Поскольку они представляют собой обычный текст, а не двоичный код, их легко читать и писать людям.
HTTP-сообщения состоят из трех частей:
Стартовая линия
Первая строка сообщения является начальной строкой, указывающей, что требуется сделать для запроса или что произошло, чтобы гарантировать ответ.
Сообщения запроса просят серверы что-то сделать с ресурсом. Начальная строка для сообщения запроса, или строка запроса, содержит метод, описывающий, какую операцию должен выполнить сервер, и URL-адрес запроса, описывающий ресурс, на котором должна выполняться операция. Строка запроса также включает версию HTTP, которая сообщает серверу, на каком диалекте HTTP говорит клиент.
Поля заголовка
За начальной строкой следует ноль или более полей заголовка. Каждое поле заголовка состоит из имени и значения, разделенных двоеточием (:) для удобства анализа. Заголовки заканчиваются пустой строкой. Добавить поле заголовка так же просто, как добавить еще одну строку.
Тело
После пустой строки следует необязательное тело сообщения, содержащее любые данные. Тела запросов передают данные на веб-сервер; тела ответа передают данные обратно клиенту. В отличие от стартовых строк и заголовков, которые являются текстовыми и структурированными, тело может содержать произвольные двоичные данные (например, изображения, видео, звуковые дорожки, программные приложения). Конечно, тело также может содержать текст.
Коды состояния
Нет необходимости знать все коды состояния, но вам нужно, по крайней мере, знать, к какой категории относится каждый код.
| Категория | Примеры | Детали |
| 1xx (информационное) | Н/Д | HTTP/1.0 не определяет никаких кодов состояния 1xx, но определяет категорию. |
| 2xx (успешно) | 200 ОК | Этот код является стандартным кодом ответа на успешный запрос. |
| | 201 Создано | Этот код должен быть возвращен для запроса POST. |
| | 204 Нет контента | Запрос принят и обработан, но ответа BODY для отправки нет. |
| 3xx(перенаправление) | 300 Множественный выбор | Этот код не используется напрямую. В нем объясняется, что категория 3xx подразумевает, что ресурс доступен в одном (или нескольких) местах, а точный ответ предоставляет более подробную информацию о том, где он находится. |
| | 301 Переехал навсегда | Заголовок HTTP-ответа Location должен содержать новый URL-адрес ресурса. |
| | 302 Временно перемещен | Заголовок HTTP-ответа Location должен содержать новый URL-адрес ресурса. |
| 4xx(ошибка клиента) | 400 Неверный запрос | Запрос не может быть понят и должен быть изменен перед повторной отправкой. |
| | 401 Неавторизованный | Этот код обычно означает, что вы не авторизованы. |
| | 403 Запрещено | Этот код обычно означает, что вы прошли аутентификацию, но ваши учетные данные не имеют доступа. |
| 5xx(ошибка сервера) | 500 Внутренняя ошибка сервера | Запрос не может быть выполнен из-за ошибки на стороне сервера. |
| | 503 Сервис недоступен | Сервер не может выполнить запрос, возможно, из-за того, что сервер перегружен или отключен для обслуживания. |
Важные заголовки
Соединение: Keep-alive
Хост: www.example.com -> это для виртуального хостинга
User-Agent: MyAwesomeWebBrowser
Словарь
Файл cookie или файл cookie сеанса
сеансовый файл cookie — это временный файл cookie, который отслеживает настройки и предпочтения пользователя при навигации по сайту.
Файл cookie сеанса удаляется, когда пользователь выходит из браузера.
Файл cookie содержит произвольный список информации name=value и прикрепляется к пользователю с помощью HTTP-заголовков ответа Set-Cookie или Set-Cookie2. Файлы cookie могут быть ограничены доменом или путем
URL-адрес
URL-адреса описывают конкретное расположение ресурса на конкретном сервере. Они точно сообщают вам, как получить ресурс из точного фиксированного местоположения. URL состоит из протокола, сервера и локального ресурса
протоколы: HTTPS, HTTP, FTP и т. д.
домен сервера → DNS
локальный ресурс - например. /index.html
Что означает порт HTTP?
Ну, на самом деле это не HTTP-порт. Это розетка. Подробности смотрите в вики
https://en.wikipedia.org/wiki/Порт_(компьютерная_сеть)
Вот стандартные:
22 - сш
80 - http
443 - https
Сессия
Совершенно очевидно, почему важно знать, с чем разговаривает пользовательский сервер (e.g. целевые рекомендации, отслеживание сессий и т. д.).
Способы хранения сессии:
- внутри cookie
- выделенное хранилище данных (например, Redis)
- липкие сеансы с отображением на балансировщике нагрузки
Виртуальный хостинг
IP-адрес состоит из 4 целых чисел от 0 до 255. Мы можем посчитать, сколько сайтов можно разместить отдельно с выделенным IP-адресом. Но реальность такова, что у нас гораздо больше сайтов, чем уникальных IP-адресов. Для этого и был придуман виртуальный хостинг. Ключевым моментом является предоставление возможности размещения нескольких сайтов на одном IP-адресе. Но как сервер, основанный на этом IP, узнает, какую HTML-страницу предоставить? С заголовком хоста, который будет содержать требуемый домен, например ==google.com==
Идемпотентные методы HTTP
Метод HTTP является идемпотентным , если идентичный запрос может быть выполнен один или несколько раз подряд с одинаковым эффектом, оставляя сервер в одном и том же состоянии. Другими словами, идемпотентный метод не должен иметь побочных эффектов (кроме ведения статистики). При правильной реализации методы GET, HEAD, PUT и DELETE являются идемпотентными, но не POST.
Используемые материалы:
[https://www.oreilly.com/library/view/http-the-definitive/1565925092/ -](https://www.oreilly.com/library/view/http-the-definitive/1565925092/ - библия :)) Библия HTTP :)
https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
https://en.wikipedia.org/wiki/Порт_(компьютерная_сеть)
https://aws.amazon.com/blogs/mobile/what-happens-when-you-type-a-url-into-your-browser/
Оригинал