Http практическое руководство

Протокол передачи гипертекста (HTTP) — это основа жизни в Интернете. Он используется каждый раз при передаче документа или в запросе AJAX. Но HTTP на удивление мало известен некоторым веб-разработчикам.

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

Переизданный урок

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


Почему REST?

REST — простой способ организации взаимодействия между независимыми системами.

REST — простой способ организации взаимодействия между независимыми системами. Он пользуется популярностью с 2005 года и вдохновляет дизайн сервисов, таких как API Twitter. Благодаря тому, что REST обеспечивает взаимодействие с такими разнообразными клиентами, как мобильные телефоны и другие веб-сайты. Теоретически, REST не привязан к сети, но почти всегда реализован как таковой и был вдохновлен HTTP. В результате REST можно использовать везде, где возможен HTTP.

Альтернативой является создание относительно сложных соглашений поверх HTTP. Часто это принимает форму новых XML-языков. Самый яркий пример — SOAP. Вам нужно выучить совершенно новый набор соглашений, но вы никогда не используете HTTP в полную силу. Поскольку REST был вдохновлён HTTP и играет на его сильные стороны, это лучший способ узнать, как работает HTTP.

После первоначального обзора мы рассмотрим каждый из строительных блоков HTTP: URL-адреса, HTTP-команды и коды ответов. Мы также рассмотрим, как использовать их в RESTful. Попутно мы проиллюстрируем теорию примером приложения, которое имитирует процесс отслеживания данных, связанных с клиентами компании через веб-интерфейс.


HTTP

HTTP — это протокол, который позволяет отправлять документы в Интернете.

HTTP — это протокол, который позволяет отправлять документы в Интернете. Протокол — это набор правил, определяющих, какие сообщения можно обменивать, и какие сообщения являются подходящими ответами для других. Другим распространенным протоколом является POP3, который вы можете использовать для извлечения электронной почты на вашем жёстком диске.

В HTTP есть две разные роли: сервер и клиент. Как правило, клиент всегда инициирует разговор; сервер отвечает. HTTP основан на тексте; то есть сообщения по сути являются битами текста, хотя тело сообщения может также содержать другие носители. Использование текста позволяет легко отслеживать обмен HTTP.

HTTP-сообщения состоят из заголовка и тела. Тело часто может оставаться пустым; оно содержит данные, которые вы хотите передать по сети, чтобы использовать их в соответствии с инструкциями в заголовке. Заголовок содержит метаданные, например информацию о кодировке; но, в случае запроса, он также содержит важные HTTP-методы. В стиле REST вы обнаружите, что данные заголовка часто более значимы, чем тела.


Шпионство HTTP на работе

Если вы используете Chrome Developer Tools или Firefox с расширением Firebug, щелкните на панели Net и установите его в enabled. После этого у вас будет возможность просматривать информацию о HTTP-запросах по мере вашего поиска. Например:

Screenshot of Firebug Net panelScreenshot of Firebug Net panelScreenshot of Firebug Net panel

Другим полезным способом ознакомиться с HTTP является использование выделенного клиента, такого как cURL.

cURL  — это инструмент command line, который доступен во всех основных операционных системах.

После установки cURL введите:

Будет отображен полный диалог HTTP. Запросам предшествует >, а ответам предшествует <.


URLS

URL — это, как вы определяете то, на чём вы хотите работать. Мы говорим, что каждый URL-адрес идентифицирует ресурс. Это те же самые URL-адреса, которые назначены веб-страницам. Фактически, веб-страница — это тип ресурса. Давайте рассмотрим более экзотический пример с нашим образцом приложения, которое управляет списком клиентов компании:

будет идентифицировать всех клиентов, в то время как

определяет клиента с именем ‘Jim’, предполагая, что он единственный с таким именем.

В этих примерах мы обычно не включаем hostname в URL, так как это не имеет никакого отношения к организации интерфейса. Тем не менее, hostname важно для того, чтобы идентификатор ресурса был уникальным во всей сети. Мы часто говорим, что вы отправляете запрос на ресурс к host. Хост включается в заголовок отдельно от пути ресурса, который идёт прямо над заголовком запроса:

1
GET /clients/jim HTTP/1.1
2

3
Host: example.com

Ресурсы лучше всего рассматривать как существительные. Например, следующее не RESTful:

Это связано с тем, что для описания действия используется URL-адрес. Это довольно фундаментальный момент в различиях систем RESTful от систем без RESTful.

Наконец, URL-адреса должны быть максимально точными; всё, что необходимо для уникальной идентификации ресурса, должно быть в URL-адресе. Вам не нужно включать в запрос данные, идентифицирующие ресурс. Таким образом, URL-адреса выступают в качестве полной карты всех данных, обрабатываемых приложением.

Но как вы определяете действие? Например, как сообщить, что вы хотите создать новую запись клиента вместо её получения? Именно здесь вступают в действие глаголы HTTP.


Глаголы HTTP

Каждый запрос указывает определенный HTTP глагол или метод в заголовке запроса. Это первое слово в заголовке запроса. Например,

означает, что используется метод GET, а  

1
DELETE /clients/anne HTTP/1.1

означает использование метода DELETE .

Глаголы HTTP сообщают серверу, что делать с данными, указанными URL.

Глаголы HTTP сообщают серверу, что делать с данными, указанными URL. Запрос может ещё содержать дополнительную информацию в своем теле, которая может потребоваться для выполнения операции — например, данные, которые вы хотите сохранить с ресурсом. Эти данные можно указать в cURL с параметром -d.

Если вы когда-либо создавали HTML-формы, то знакомы с двумя из наиболее важных HTTP-глаголов: GET и POST. Но есть гораздо больше доступных HTTP-глаголов. Наиболее важными для построения RESTful API являются GET, POST, PUT и DELETE. Доступны другие методы, такие как HEAD и OPTIONS, но они более редки (если вы хотите знать обо всех других методах HTTP, официальным источником является IETF).

GET

GET — это самый простой тип HTTP-запроса; которым браузер пользуется каждый раз, когда вы нажимаете ссылку или вводите URL-адрес в адресную строку. Он инструктирует сервер передавать клиенту данные, идентифицированные URL-адресом. Никогда не последует изменений данных на стороне сервера в результате запроса GET. В этом смысле GET-запрос доступен только для чтения, но, конечно, как только клиент получит данные, он может самостоятельно выполнять любые операции с ними, например, форматировать для отображения.

PUT

Запрос PUT используется, когда вы хотите создать или обновить ресурс, указанный URL-адресом. Например,

может создать клиента с именем Robin на сервере. Вы заметите, что REST полностью независим от бэкэнда; в запросе нет ничего, что информирует сервер о том, как данные должны создаваться — просто так должно быть. Это позволяет вам легко менять базовую технологию по необходимости. Запросы PUT содержат данные для использования при обновлении или создании ресурса в body. В cURL вы можете добавить данные в запрос с помощью  -d.

1
curl -v -X PUT -d "some text"

DELETE

DELETE должен выполнять противоположное PUT; его следует использовать, если вы хотите удалить ресурс, указанный URL-адресом запроса.

1
curl -v -X DELETE /clients/anne

Это приведёт к удалению всех данных, связанных с ресурсом, идентифицированных /clients/anne.

POST

POST используется, когда обработка, которую вы хотите выполнить на сервере, должна повторяться, если запрос POST повторяется (то есть, они не являются идемпотентными, подробнее об этом ниже). Кроме того, POST-запросы должны вызывать обработку body запроса как подчинённого URL-адреса, который вы отправляете.

Проще говоря:

не должен вызывать изменение ресурса в /clients/ сам, но ресурс URL начинается с него /clients/. Например, он может добавить в список нового клиента, с id, сгенерированным сервером.

1
/clients/some-unique-id

Запросы PUT легко используются вместо запросов POST и наоборот. Некоторые системы используют только один, некоторые используют POST для создания операций и PUT для операций обновления (поскольку с запросом PUT вы всегда указываете полный URL-адрес), некоторые используют POST для обновлений и PUT для создания.

Часто запросы POST используются для запуска операций на сервере, которые не вписываются в парадигму Create/Update/Delete; но это, однако, выходит за рамки REST. В нашем примере мы будем полностью придерживаться PUT.


Классификация методов HTTP  

Безопасные и небезопасные методы:

безопасными являются методы, которые никогда не изменяют ресурсы. Единственными безопасными методами, из четырёх перечисленных выше, является GET. Другие небезопасны, так как они могут привести к модификации ресурсов.

Idempotent методы:

Эти методы достигают того же результата, независимо от того, сколько раз запрос повторяется: это GET, PUT и DELETE. Единственным неидемпотентным методом является POST. PUT и DELETE, считающиеся идемпотентами, могут быть неожиданными, хотя, на самом деле, это довольно легко объяснить: повторение метода PUT с точно таким же body должно модифицировать ресурс таким образом, чтобы он оставался идентичным описанному в предыдущем запросе PUT: ничего не изменится! Аналогичным образом, нет смысла дважды удалять ресурс. Из этого следует, что независимо от того, сколько раз запрос PUT или DELETE повторяется, результат должен быть таким же, как если бы это было сделано только один раз.

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


Представительства

HTTP-клиент и HTTP-сервер обмениваются информацией о ресурсах, определённых URL-адресами.

Мы можем суммировать то, что мы узнали до сих пор, следующим образом: HTTP-клиент и HTTP-сервер обмениваются информацией о ресурсах, определённых URL-адресами.

Мы говорим, что запрос и ответ содержат представление ресурса. Под представлением мы подразумеваем информацию в определённом формате о состоянии ресурса или о том, каким это состояние должно быть в будущем. Оба, и header, и body — являются частями представления.

Заголовки HTTP, содержащие метаданные, жёстко определяются спецификацией HTTP; они могут содержать только простой текст и должны быть отформатированы определённым образом.

Тело может содержать данные в любом формате, и именно здесь видна сила HTTP. Вы знаете, что можете отправлять простой текст, изображения, HTML и XML на любом человеческом языке. Через метаданные запроса или различные URL-адреса вы можете выбирать между различными представлениями для одного и того же ресурса. Например, вы можете отправить веб-страницу в браузеры и JSON в приложения.

HTTP-ответ должен указывать тип содержимого body. Это делается в заголовке, в поле Content-Type; например:

1
Content/Type: application/json

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


Библиотеки клиента HTTP

cURL — это, чаще всего, HTTP-решение для PHP-разработчиков.

Чтобы поэкспериментировать с различными методами запроса, вам нужен клиент, который позволит указать, какой метод использовать. К сожалению, формы HTML не подходят для счёта, так как они позволяют делать только запросы GET и POST. В реальной жизни API-интерфейсы доступны программно через отдельное клиентское приложение или через JavaScript в браузере.

Именно поэтому в дополнение к серверу важно иметь хорошие возможности HTTP-клиента на выбранном вами языке программирования.

Очень популярная клиентская HTTP-библиотека, опять же, cURL. Вы уже были ознакомлены с командой cURL ранее в этом уроке. CURL включает в себя как автономную программу командной строки, так и библиотеку, которая может использоваться различными языками программирования. В частности, cURL является, чаще всего, идеальным решением HTTP-клиента для разработчиков PHP. Другие языки, такие как Python, предлагают больше собственных клиентских HTTP-библиотек.


Настройка примера приложения

Я хочу показать как можно более низкий уровень функциональности.

Наш пример PHP-приложения чрезвычайно тощ. Я хочу выставить  как можно более низкоуровневую функциональность, без какой-либо магии framework . Я также не хотел использовать настоящий API, например, Twitter, потому что они могут неожиданно меняться, вам нужно настроить аутентификацию, что может быть проблемой и вы не сможете изучить реализацию.

Чтобы запустить пример приложения, вам необходимо установить PHP5 и веб-сервер с механизмом для запуска PHP. Текущая версия должна быть не ниже версии 5.2, чтобы иметь доступ к функциям json_encode () и json_decode ().

Что касается серверов, наиболее распространенным вариантом является Apache с mod_php, но вы можете использовать любые альтернативы, которые вам удобны. Существует пример конфигурации Apache, который содержит правила перезаписи, которые помогут вам быстро настроить приложение. Все запросы к любому URL, начиная с /clients/, должны быть направлены в наш файл server.php.

В Apache вам нужно включить mod_rewrite и поместить прилагаемую конфигурацию mod_rewrite где-нибудь в вашей конфигурации Apache или в ваш файл .htacess. Таким образом, server.php будет отвечать на все запросы, поступающие с сервера. То же самое должно быть достигнуто с Nginx, или с любым другим сервером, который вы решите использовать.


Как работает пример приложения

Есть два ключа по обработке запросов REST. Первый ключ — инициировать различную обработку, в зависимости от метода HTTP, даже когда URL-адреса одинаковы. В PHP в глобальном массиве $ _SERVER есть переменная, которая определяет, какой метод был использован для выполнения запроса:

1
$_SERVER['REQUEST_METHOD']

Эта переменная содержит имя метода в виде строки, например ‘GET‘, ‘PUT‘ и далее.

Другой ключ — узнать, какой URL был запрошен. Для этого мы используем другую стандартную переменную PHP:

1
$_SERVER['REQUEST_URI']

Эта переменная содержит URL-адрес, начинающийся с первой косой черты. Например, если имя хоста — ‘example.com‘, ‘http://example.com/‘ вернётся ‘/‘, как ‘http://example.com/test/‘ вернётся ‘/test/‘.

Давайте сначала попытаемся определить, какой URL-адрес был вызван. Мы рассматриваем только URL-адреса, начинающиеся с  ‘clients‘. Все остальные недействительны.

1
$resource = array_shift($paths);
2

3
if ($resource == 'clients') {
4
    $name = array_shift($paths);
5

6
    if (empty($name)) {
7
        $this->handle_base($method);
8
    } else {
9
        $this->handle_name($method, $name);
10
    }
11

12
} else {
13
    // We only handle resources under 'clients'

14
    header('HTTP/1.1 404 Not Found');
15
}

У нас есть два возможных результата:

  • Ресурс — это клиенты, и в этом случае мы возвращаем полный список
  • Существует еще один идентификатор

Если есть ещё один идентификатор, мы предполагаем, что это имя клиента, и, опять же, перенаправляем его в другую функцию, в зависимости от method. Мы используем оператор switch, которого следует избегать в реальном приложении:

1
switch($method) {
2
  case 'PUT':
3
      $this->create_contact($name);
4
      break;
5

6
  case 'DELETE':
7
      $this->delete_contact($name);
8
      break;
9

10
  case 'GET':
11
      $this->display_contact($name);
12
      break;
13

14
  default:
15
      header('HTTP/1.1 405 Method Not Allowed');
16
      header('Allow: GET, PUT, DELETE');
17
      break;
18
  }

Коды ответов

Коды ответа HTTP стандартизируют способ информирования клиента о результате его запроса.

Вы могли заметить, что пример приложения использует PHP header(), передавая некоторые странные строки в качестве аргументов. Функция header() печатает HTTP headers и гарантирует, что они отформатированы соответствующим образом. Заголовки должны быть первым в ответе, поэтому не стоит выводить что-либо ещё до того, как вы закончите с заголовками. Иногда ваш HTTP-сервер может быть настроен для добавления других заголовков в дополнение к тем, которые вы указали в коде.

Заголовки содержат все виды метаинформации; например, текстовую кодировку, используемую в body сообщения, или MIME-тип содержимого body. В этом случае мы явно указываем коды ответа HTTP. Коды ответа HTTP стандартизируют способ информирования клиента о результате его запроса. По умолчанию PHP возвращает код ответа 200, что означает, что ответ выполнен успешно.

Сервер должен вернуть наиболее подходящий код ответа HTTP; таким образом клиент может попытаться исправить свои ошибки, если они есть. Большинство людей знакомы с распространенным кодом ответа 404 Not Found, однако есть много более доступных, в соответствии множеству ситуаций.

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

Вот несколько HTTP-кодов ответа, которые часто используются с REST:

200 OK

Этот код ответа указывает, что запрос был успешным.

201 Created

Это означает, что запрос был успешным и был создан ресурс. Он используется в случае успеха запроса PUT или POST.

400 Bad Request

Запрос был утерян. Это происходит особенно с запросами POST и PUT, когда данные не проходят валидацию или находятся в неправильном формате.

404 Not Found

Этот ответ указывает, что необходимый ресурс не найден. Обычно это относится ко всем запросам, которые указывают на URL-адрес без соответствующего ресурса.

401 Unauthorized

Эта ошибка означает, что вам необходимо выполнить проверку подлинности перед доступом к ресурсу.

405 Method Not Allowed

Используемый метод HTTP не поддерживается для этого ресурса.

409 Conflict

Это указывает на конфликт. Например, вы используете запрос PUT для создания одного и того же ресурса дважды.

500 Internal Server Error

Когда всё остальное терпит неудачу; как правило, ответ 500 используется, когда обработка завершается неудачно из-за непредвиденных обстоятельств на стороне сервера, что вызывает ошибку сервера.


Выполнение образца приложения

Давайте начнем с простого извлечения информации из приложения. Нам нужны детали клиента, ‘jim‘, поэтому давайте отправим простой запрос GET на URL этого ресурса:

1
curl -v http://localhost:80/clients/jim

Это отобразит полные сообщения headers. Последней строкой ответа будет body сообщения; в этом случае это будет JSON, содержащий адрес Jim (помните, что пропуск имени метода приведет к GET-запросу, а также замените localhost: 80 на имя сервера и порт, который вы используете).

Затем мы можем получить информацию для всех клиентов одновременно:

1
curl -v http://localhost:80/clients/

Чтобы создать нового клиента с именем Paul …

1
curl -v -X PUT http://localhost:80/clients/paul -d '{"address":"Sunset Boulevard" }

и вы получите список всех клиентов, содержащих Paul в качестве подтверждения.

Наконец, чтобы удалить клиента:

1
curl -v -X DELETE http://localhost:80/clients/anne

Вы обнаружите, что возвращённый JSON больше не содержит никаких данных об Anne.

Если вы пытаетесь получить несуществующего клиента, например:

1
curl -v http://localhost:80/clients/jerry

Вы получите ошибку 404, в то время как при попытке создать уже существующего клиента:

curl -v -X PUT http://localhost:80/clients/anne

вместо этого получите ошибку 409.


Заключение

В общем, чем меньше предположений за пределами HTTP вы делаете, тем лучше.

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

Я использовал PHP в этом уроке, потому что это, скорее всего, язык, наиболее знакомый читателям Nettuts +. Тем не менее, PHP, хотя и предназначен для Интернета, вероятно, не самый лучший язык для работы при REST-способе, поскольку он обрабатывает запросы PUT совсем иначе, чем GET и POST.

Помимо PHP, вы можете принять во внимание следующее:

  • Различные Ruby frameworks (Rails и Sinatra)
  • В Python есть отличная поддержка REST. Должны работать Plain Django и WebOb, или Werkzeug.
  • node.js отлично поддерживает REST

Среди приложений, которые пытаются придерживаться принципов REST, классическим примером является Atom Publishing Protocol, хотя на самом деле он не используется слишком часто на практике. За современным приложением, основанным на философии использования HTTP в полной мере, обратитесь к Apache CouchDB.

Удачи!

ЛР-3 Исследование HTTP-запросов и REST. Разработка серверной части (backend) на Node.js Express

Ключевые слова

HTTP-протокол, HTTP-запросы, REST, REST API, Node.js, Express, Postman

Цель работы

Познакомиться с HTTP-протоколом и технологией взаимодействия компонентов REST. Изучить работу HTTP-запросов.

Изучить принцип тестирования REST API с помощью Postman.

Изучить принципы работы сервера на примере Express на Node.js.

Научиться разрабатывать простой сервер на Express.

Потребуется ПО

  • редактор кода VS Code / Sublime / Notepad++

  • Node.js (включает npm)

  • MongoDB Native Driver (через npm)

  • Json-server (через npm)

  • Express (через npm)

  • Postman

Также потребуется ПО из lab-1:

  • MongoDB

  • командная оболочка системы (cmd, PowerShell, git bash, консоль VS Code)

Быстрый переход

  • Теоретическая часть

  • 1 HTTP-протокол

  • Cхема протокола

  • HTTP-сообщения запроса и ответа

  • HTTP-методы

  • Коды состояний

  • 2 REST

  • 3 Postman

  • 4 Express

  • Практическая часть 1 — Исследование HTTP-запросов и REST

  • Подготовка

  • Выполнение

  • Содержание отчета

  • Практическая часть 2 — Разработка серверной части (backend) на Node.js Express

  • Подготовка

  • Выполнение

  • Содержание отчета

  • Вопросы для самоконтроля

  • Информационные ресурсы

Теоретическая часть

1 HTTP-протокол

HTTP (англ. HyperText Transfer Protocol — протокол передачи гипертекста) — протокол прикладного уровня передачи данных изначально в виде гипертекстовых документов в формате HTML, в настоящий момент используется для передачи произвольных данных. Основой HTTP является технология клиент-сервер, т.е. предполагается существование:

  • клиентов, которые инициируют соединение и посылают запрос

  • серверов, которые ожидают соединения для получения запроса, производят необходимые действия и возвращают обратно сообщение с результатом (wiki)

Cхема протокола

HTTP работает по следующей схеме:

  1. Клиент инициирует соединение.

  2. Клиент отправляет запрос посредством HTTP-сообщения.

  3. Сервер обрабатывает запрос.

  4. Сервер отправляет ответ посредством HTTP-сообщения.

  5. Клиент обрабатывает ответ.

  6. Клиент закрывает или переиспользует соединение (начиная с HTTP/1.1) для дальнейших запросов.

Актуальные версии HTTP — 1.1 (наиболее распространена) и 2.0.

HTTP-сообщения запроса и ответа

HTTP-сообщения запроса имеют следующую структуру:

  • Строка запроса, которая содержит:
  1. HTTP-метод (см. ниже), определяющий операцию, которую клиент хочет выполнить — GET

  2. Путь к ресурсу — /doc/test.html

  1. Версию HTTP-протокола — HTTP/1.1
  • Заголовки, которые предоставляют дополнительную информацию для сервера

  • Тело для некоторых методов (POST), которое содержит отправляемые данные

HTTP-сообщения ответа имеют следующую структуру:

  • Строка статуса, которая содержит:
  1. Версию HTTP-протокола — HTTP/1.1

  2. Код состояния — 200

  3. Сообщение состояния — ‘OK’

  • Заголовки, которые предоставляют дополнительную информацию для клиента

  • Тело, которое содержит отправляемые данные

Пример — запрос страницы в браузере

Самый простой способ увидеть структуру HTTP-сообщений — открыть любую страницу в браузере Chrome и зайти в инструменты разработчика (F12 -> Network -> Headers):

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

HTTP-методы

Название HTTP-метода — ключевое слово, указывающее на основную операцию над ресурсом.

Существует несколько методов:

  1. GET — используется в основном для запроса данных с сервера.

Например, GET /path/resource?param1=value1&param2=value2 HTTP/1.1 — запрос ресурса ‘/path/resource’.

Часть после символа ‘?’ — query string («строка запроса»). С ее помощью можно передать дополнительную информацию, а также инициировать какой-либо процесс или вообще изменить семантическое назначение GET (запрашивать) и передавать данные (но ограниченный размер).

Query string видно в url браузера.

Query string может быть в заголовке любого запроса — это не уникальная особенность GET.

  1. POST — используется для отправки данных на сервер, например, данные форм.

В отличие от GET имеет тело запроса, в котором и содержаться передаваемые данные. При этом обычный пользователь не видит данные в url как при использовании query string в GET-методе. Данные могут быть гораздо больших объемов чем в query string.

Например,

  1. PUT — используется для изменения существующих данных

  2. DELETE — используется для удаления существующих данных

  3. HEAD — используется для проверки существования ресурса

Метод аналогичен GET, но ответ сервера не содержит тело, только заголовки.

  1. PATCH

  2. TRACE

  3. CONNECT

GET и POST — наиболее часто используемые HTTP-методы.

POST, GET, PUT и DELETE — представляют CRUD-операции с данными:

HTTP CRUD
POST Create
GET Read
PUT Update
DELETE Delete

Коды состояний

Код состояния информирует клиента об успешности выполнения его запроса.

Код состояния выражается трехзначным числом, где количество сотен указывает на тип кода.

Кодов состояний довольно много (wiki). Вот некоторые примеры:

  1. 1xx: Informational (информационные):
  • 101 Switching Protocols («переключение протоколов»)

  • 102 Processing («идёт обработка»)

  1. 2xx: Success («успешно»):
  • 200 OK («все в порядке»)

  • 201 Created («создано»)

  • 202 Accepted («принято»)

  1. 3xx: Redirection (перенаправление):
  • 302 Moved Temporarily («перемещено временно»)

  • 307 Temporary Redirect («временное перенаправление»)

  1. 4xx: Client Error (ошибка клиента):
  • 400 Bad Request («неверный запрос»)

  • 401 Unauthorized («не авторизован «)

  • 403 Forbidden («запрещено»)

  • 404 Not Found («не найдено»)

  • 405 Method Not Allowed («метод не поддерживается»)

  • 418 I’m a teapot («я — чайник»)

  1. 5xx: Server Error (ошибка сервера):
  • 500 Internal Server Error («внутренняя ошибка сервера»)

  • 501 Not Implemented («не реализовано»)

  • 502 Bad Gateway («плохой, ошибочный шлюз»)

  • 503 Service Unavailable («сервис недоступен»)

  • 504 Gateway Timeout («шлюз не отвечает»)

  • 520 Unknown Error («неизвестная ошибка»)

2 REST

REST (от англ. Representational State Transfer — «передача состояния представления») — архитектурный стиль взаимодействия компонентов распределённого приложения в сети. REST представляет собой согласованный набор ограничений, учитываемых при проектировании распределённой гипермедиа-системы. В определённых случаях (интернет-магазины, поисковые системы, прочие системы, основанные на данных) это приводит к повышению производительности и упрощению архитектуры. В широком смысле компоненты в REST взаимодействуют наподобие взаимодействия клиентов и серверов (wiki).

REST использует HTTP-запросы (в т.ч. с параметрами через url), но придает им больше семантичности (каждый метод отвечает строго за определнную операцию).

REST-методы состоят из названия HTTP-метода и ресурса (используется относительный путь), а также описания тела и прочих параметров соответствующих HTTP-методов:

  • GET /api/clients — «получить всех клиентов»

  • GET /api/clients/1 — «получить клиента с id: 1»

  • POST /api/clients — «добавить нового клиента»

  • PUT /api/clients/1 — «изменить клиента с id: 1»

  • DELETE /api/clients/1 — «удалить клиента с id: 1»

Для веб-служб, построенных с учётом REST (то есть не нарушающих накладываемых им ограничений), применяют термин «RESTful».

Совокупность всех задокументированных REST-методов (название, путь и описание параметров соответствующих HTTP-запросов) представляет RESTful API сервера — программный интерфейс, который позволяет клиенту взаимодействовать с сервером.

Не существует «официального» стандарта для RESTful API, т.к. REST является архитектурным стилем, а не протоколом (как например SOAP). Несмотря на то, что REST не является стандартом сам по себе, большинство RESTful-реализаций используют такие стандарты, как HTTP, URL, JSON и XML.

3 Postman

Postman — приложение, которое представляется клиентом и позволяет отправлять запросы на сервер и просматривать ответы сервера. Приложение имеет удобный GUI («графический интерфейс») для настройки параметров запросов и просмотра ответов сервера. Другими словами, Postman используется для проверки RESTful API сервера.

Основные элементы приложения показаны на рисунке:

Имеется возможность выбирать тип запроса, путь запроса, менять заголовки и т.д.

Например, отправка запрос GET /api/clients будет выглядеть как на рисунке выше.

Для POST /api/clients необходимо заполнить тело запроса и выбрать формат «form-data»:

4 Express

Express — Node.js-фреймворк для написания сервера. Устанавливается как пакет ‘express’ (npm i express).

Структура кода express-сервера выглядит примерно так:

(см. ./express/index.js)

Для упрощения не используем модульное построение проекта.

Основными элементами express-сервера являются middlewares («функцией промежуточной обработки»):

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});
app.get('/api/client/:id', function (req, res, next) {
  res.send('HI');
});

middleware используется в качестве параметра метода сервера app. Такие методы соответствуют REST-запросам: app.get(), app.post(), app.put(), app.delete() или app.use() — универсальный метод, сработает при любом REST-запросе на этот путь независимо от метода.

Смысл middleware — в извлечении необходимых свойства из объекта запроса req, формирование структуры ответа и вызове необходимых методов в объекте ответа res (req, res — это обычные js-объекты).

Опциональный аргумент next — это callback, который используется для следующего обработчика этого же пути (если он есть).

Важными свойствами req являются:

  • req.params — объект параметров. Например, если придет запрос ‘GET /api/clients/1’ в middleware ‘app.get(‘/api/client/:id’, function() { … })’, то req.params === { id: 1 }

  • req.headers — объект заголовков

  • req.body — объект тела

Важными методами res являются:

  • res.set() — метод для установки заголовков. Например, res.set('Content-Type', 'text/plain')

  • res.status() — метод для установки кода состояния. Например, res.status(200)

  • res.send() — метод для отправки тела в произвольном формате. Например, res.send('Hi, client!')

  • res.json() — метод для отправки тела в формате JSON. Например, res.send({ ... })

Полный список свойств и методов можно посмотреть в официальной документации к express (req, res).

Внутри middleware до момента отправки ответа методами res.send() или res.json() можно выполнять любые манипуляции с запросом и ответом, например, можно обратиться к БД:

app.get('/api/clients', function (req, res) {
  var client = new MongoClient(url, { useNewUrlParser: true });

  client.connect(function (err) {
    if (err) {
      console.log(err);
      res.status(500);
    } else {
      console.log('Connected successfully to server');

      var db = client.db(dbName);
      var collection = db.collection('clients');

      collection.find({}).toArray(function (err, docs) {
        // сортируем результаты
        var sortedDocs = (docs || []).sort(idComparator);

        res.json(sortedDocs);
      });

      client.close();
    }
  });
});

Практическая часть 1 — Исследование HTTP-запросов и REST

В данной части предполагается работа с готовым сервером — json-server. Преимущество json-server’а перед реальной связкой «сервер приложений — сервер БД» в том, что он использует .json-файл в качестве БД. Нет необходимости подключаться к MongoDB. Это удобно при разработке и тестировании клиента или, например, при изучении работы REST API. Именно научиться работать с REST API сервера и программой Postman — задача данной части.

Подготовка

  1. Считаем, что Node.js уже установлен в системе (в лаб. 2).

  2. Установите Postman.

  3. Подготовьте локальную копию репозитория к работе:

Cкопируйте ./lab-3/json-server в ./lab-3/work и работайте там.

Откройте консоль в ./lab-3/json-server(./lab-3/work/json-server) и введите команду npm i.

  1. Введите в консоли npm start — запустится сервер на порту 3017:

Оставьте сервер работающим на время выполнения лабораторной.

По умолчанию в качестве БД сервер использует файл db.json, в котором всего одна «коллекция» — clients. Вы можете заменить данные вашими.

После выполнения лабораторной отключите json-server (ctrl + C в консоли)!

Выполнение

Используя Postman, последовательно выполните серию запросов к json-server’у. Зафиксируйте параметры запроса и результаты. Проанализируйте тело и заголовки ответа.

  1. Выполните GET-запрос
  • тип: GET
  • путь: localhost:3017/api/clients
  • формат ответа: JSON
  1. Выполните POST-запрос
  • тип: POST
  • путь: localhost:3017/api/clients
  • тело: {
    «first_name»: «New First Name»,
    «last_name»: «New Last Name»
    }
  • формат тела: form-data
  • формат ответа: JSON
  1. GET localhost:3017/api/clients/1

  2. PUT localhost:3017/api/clients/2

  3. DELETE localhost:3017/api/clients/3

Содержание отчета

Скрины из Postman и описание параметров запроса и ответа (метод, путь, заголовки, тело, статус ответа и т.д.) — для каждого запроса.

Практическая часть 2 — Разработка серверной части (backend) на Node.js Express

Подготовка

  1. Запустите сервер MongoDB и оставьте его работающим:

./bin/mongod --dbpath c:/mongodb/data --port 27017

На всякий случай сделайте резервное копирование своей БД:

./bin/mongodump --db [dbname] --out c:/mongodb/backup

Для восстановления БД используйте:

./bin/mongorestore --db [dbname] --drop c:/mongodb/backup/[dbname]

  1. Подготовьте локальную копию репозитория к работе:

Cкопируйте ./lab-3/express в ./lab-3/work и работайте там.

Откройте консоль в ./lab-3/express(./lab-3/work/express) и введите команду npm i.

Выполнение

  1. Доработайте код сервера ./lab-3/express/index.js(./lab-3/work/express/index.js) в соответствии с вашей БД.

Необходимо написать REST API минимум для 3ех коллекций!

  1. Введите в консоли npm start — запустится сервер на порту 3017.

Оставьте сервер работающим на время выполнения лабораторной.

Важно! Порт используется тот же, что и для json-server’a. Поэтому не забудьте отключить json-server (ctrl + C в консоли) перед выполнением части 2.

  1. Используя Postman протестируйте REST API вашего сервера и зафиксируйте результаты.

Содержание отчета

Скрины из Postman и описание параметров запроса и ответа (метод, путь, заголовки, тело, статус ответа и т.д.) — для каждого запроса.

Вопросы для самоконтроля

Информационные ресурсы

HTTP, REST

  • HTTP (wiki)

  • Обзор протокола HTTP (developer.mozilla.org)

  • Что такое протокол HTTP и как он работает (link)

  • Простым языком об HTTP (habr)

  • HTTP-коды состояний (wiki)

  • REST (wiki)

  • REST простым языком (medium)

Express

  • Официальный ресурс (expressjs.com)

  • Как использовать middleware (expressjs.com)

  • Пишем API на NodeJS от loftblog (youtube)

  • Инструмент Postman (youtube)

Полезные сервисы

  • Все коды ошибок HTTP (link)

Node.js — это серверная платформа. Основная задача сервера — как можно быстрее и эффективнее обрабатывать запросы, поступающие от клиентов, в частности — от браузеров. Восьмая часть перевода руководства по Node.js, которую мы публикуем сегодня, посвящена протоколам HTTP и WebSocket.

[Советуем почитать] Другие части цикла

Часть 1: Общие сведения и начало работы
Часть 2: JavaScript, V8, некоторые приёмы разработки
Часть 3: Хостинг, REPL, работа с консолью, модули
Часть 4: npm, файлы package.json и package-lock.json
Часть 5: npm и npx
Часть 6: цикл событий, стек вызовов, таймеры
Часть 7: асинхронное программирование
Часть 8: Руководство по Node.js, часть 8: протоколы HTTP и WebSocket
Часть 9: Руководство по Node.js, часть 9: работа с файловой системой
Часть 10: Руководство по Node.js, часть 10: стандартные модули, потоки, базы данных, NODE_ENV
Полная PDF-версия руководства по Node.js

Что происходит при выполнении HTTP-запросов?

Поговорим о том, как браузеры выполняют запросы к серверам с использованием протокола HTTP/1.1.

Если вы когда-нибудь проходили собеседование в IT-сфере, то вас могли спросить о том, что происходит, когда вы вводите нечто в адресную строку браузера и нажимаете Enter. Пожалуй, это один из самых популярных вопросов, который встречается на подобных собеседованиях. Тот, кто задаёт подобные вопросы, хочет узнать, можете ли вы объяснить некоторые довольно-таки простые концепции и выяснить, понимаете ли вы принципы работы интернета.

Этот вопрос затрагивает множество технологий, понимать общие принципы которых — значит понимать, как устроена одна из самых сложных систем из когда-либо построенных человечеством, которая охватывает весь мир.

▍Протокол HTTP

Современные браузеры способны отличать настоящие URL-адреса, вводимые в их адресную строку, от поисковых запросов, для обработки которых обычно используется заданная по умолчанию поисковая система. Мы будем говорить именно об URL-адресах. Если вы введёте в строку браузера адрес сайта, вроде flaviocopes.com, браузер преобразует этот адрес к виду http://flaviocopes.com, исходя из предположения о том, что для обмена данными с указанным ресурсом будет использоваться протокол HTTP. Обратите внимание на то, что в Windows то, о чём мы будем тут говорить, может выглядеть немного иначе, чем в macOS и Linux.

▍Фаза DNS-поиска

Итак, браузер, начиная работу по загрузке данных с запрошенного пользователям адреса, выполняет операцию DNS-поиска (DNS Lookup) для того, чтобы выяснить IP-адрес соответствующего сервера. Символьные имена ресурсов, вводимые в адресную строку, удобны для людей, но устройство интернета подразумевает возможность обмена данными между компьютерами с использованием IP-адресов, которые представляют собой наборы чисел наподобие 222.324.3.1 (для протокола IPv4).

Сначала, выясняя IP-адрес сервера, браузер заглядывает в локальный DNS-кэш для того, чтобы узнать, не выполнялась ли недавно подобная процедура. В браузере Chrome, например, есть удобный способ посмотреть DNS-кэш, введя в адресной строке следующий адрес: chrome://net-internals/#dns.

Если в кэше ничего найти не удаётся, браузер использует системный вызов POSIX gethostbyname для того, чтобы узнать IP-адрес сервера.

▍Функция gethostbyname

Функция gethostbyname сначала проверяет файл hosts, который, в macOS или Linux, можно найти по адресу /etc/hosts, для того, чтобы узнать, можно ли, выясняя адрес сервера, обойтись локальными сведениями.

Если локальными средствами разрешить запрос на выяснение IP-адреса сервера не удаётся, система выполняет запрос к DNS-серверу. Адреса таких серверов хранятся в настройках системы.

Вот пара популярных DNS-серверов:

  • 8.8.8.8: DNS-сервер Google.
  • 1.1.1.1: DNS-сервер CloudFlare.

Большинство людей используют DNS-сервера, предоставляемые их провайдерами. Браузер выполняет DNS-запросы с использованием протокола UDP.

TCP и UDP — это два базовых протокола, применяемых в компьютерных сетях. Они расположены на одном концептуальном уровне, но TCP — это протокол, ориентированный на соединениях, а для обмена UDP-сообщениями, обработка которых создаёт небольшую дополнительную нагрузку на системы, процедура установления соединения не требуется. О том, как именно происходит обмен данными по UDP, мы говорить не будем.

IP-адрес, соответствующий интересующему нас доменному имени, может иметься в кэше DNS-сервера. Если это не так — он обратиться к корневому DNS-серверу. Система корневых DNS-серверов состоит из 13 серверов, от которых зависит работа всего интернета.

Надо отметить, что корневому DNS-серверу неизвестны соответствия между всеми существующими в мире доменными именами и IP-адресами. Но подобным серверам известны адреса DNS-серверов верхнего уровня для таких доменов, как .com, .it, .pizza, и так далее.

Получив запрос, корневой DNS-сервер перенаправляет его к DNS-серверу домена верхнего уровня, к так называемому TLD-серверу (от Top-Level Domain).

Предположим, браузер ищет IP-адрес для сервера flaviocopes.com. Обратившись к корневому DNS-серверу, браузер получит у него адрес TLD-сервера для зоны .com. Теперь этот адрес будет сохранён в кэше, в результате, если будет нужно узнать IP-адрес ещё какого-нибудь URL из зоны .com, к корневому DNS-серверу не придётся обращаться снова.

У TLD-серверов есть IP-адреса серверов имён (Name Server, NS), средствами которых и можно узнать IP-адрес по имеющемуся у нас URL. Откуда NS-сервера берут эти сведения? Дело в том, что если вы покупаете домен, доменный регистратор отправляет данные о нём серверам имён. Похожая процедура выполняется и, например, при смене хостинга.

Сервера, о которых идёт речь, обычно принадлежат хостинг-провайдерам. Как правило, для защиты от сбоев, создаются по несколько таких серверов. Например, у них могут быть такие адреса:

  • ns1.dreamhost.com
  • ns2.dreamhost.com
  • ns3.dreamhost.com

Для выяснения IP-адреса по URL, в итоге, обращаются к таким серверам. Именно они хранят актуальные данные об IP-адресах.

Теперь, после того, как нам удалось выяснить IP-адрес, стоящий за введённым в адресную строку браузера URL, мы переходим к следующему шагу нашей работы.

▍Установление TCP-соединения

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

▍Отправка запроса

Запрос представляет собой структурированный в соответствии с правилами используемого протокола фрагмент текста. Он состоит из трёх частей:

  • Строка запроса.
  • Заголовок запроса.
  • Тело запроса.

Строка запроса

Строка запроса представляет собой одну текстовую строку, в которой содержатся следующие сведения:

  • Метод HTTP.
  • Адрес ресурса.
  • Версия протокола.

Выглядеть она, например, может так:

GET / HTTP/1.1

Заголовок запроса

Заголовок запроса представлен набором пар вида поле: значение. Существуют 2 обязательных поля заголовка, одно из которых — Host, а второе — Connection. Остальные поля необязательны.

Заголовок может выглядеть так:

Host: flaviocopes.com
Connection: close

Поле Host указывает на доменное имя, которое интересует браузер. Поле Connection, установленное в значение close, означает, что соединение между клиентом и сервером не нужно держать открытым.

Среди других часто используемых заголовков запросов можно отметить следующие:

  • Origin
  • Accept
  • Accept-Encoding
  • Cookie
  • Cache-Control
  • Dnt

На самом деле, их существует гораздо больше.

Заголовок запроса завершается пустой строкой.

Тело запроса

Тело запроса необязательно, в GET-запросах оно не используется. Тело запроса используется в POST-запросах, а также в других запросах. Оно может содержать, например, данные в формате JSON.

Так как сейчас речь идёт о GET-запросе, тело запроса будет пустым, с ним мы работать не будем.

▍Ответ

После того, как сервер получает отправленный клиентом запрос, он его обрабатывает и отправляем клиенту ответ.

Ответ начинается с кода состояния и с соответствующего сообщения. Если запрос выполнен успешно, то начало ответа будет выглядеть так:

200 OK

Если что-то пошло не так, тут могут быть и другие коды. Например, следующие:

  • 404 Not Found
  • 403 Forbidden
  • 301 Moved Permanently
  • 500 Internal Server Error
  • 304 Not Modified
  • 401 Unauthorized

Далее в ответе содержится список HTTP-заголовков и тело ответа (которое, так как запрос выполняет браузер, будет представлять собой HTML-код).

Разбор HTML-кода

После того, как браузер получает ответ сервера, в теле которого содержится HTML-код, он начинает его разбирать, повторяя вышеописанный процесс для каждого ресурса, который нужен для формирования страницы. К таким ресурсам относятся, например, следующие:

  • CSS-файлы.
  • Изображения.
  • Значок веб-страницы (favicon).
  • JavaScript-файлы.

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

О создании простого сервера средствами Node.js

Теперь, после того, как мы разобрали процесс взаимодействия браузера и сервера, вы можете по-новому взглянуть на раздел Первое Node.js-приложение из первой части этой серии материалов, в котором мы описывали код простого сервера.

Выполнение HTTP-запросов средствами Node.js

Для выполнения HTTP-запросов средствами Node.js используется соответствующий модуль. В приведённых ниже примерах применяется модуль https. Дело в том, что в современных условиях всегда, когда это возможно, нужно применять именно протокол HTTPS.

▍Выполнение GET-запросов

Вот пример выполнения GET-запроса средствами Node.js:

const https = require('https')
const options = {
  hostname: 'flaviocopes.com',
  port: 443,
  path: '/todos',
  method: 'GET'
}
const req = https.request(options, (res) => {
  console.log(`statusCode: ${res.statusCode}`)
  res.on('data', (d) => {
    process.stdout.write(d)
  })
})
req.on('error', (error) => {
  console.error(error)
})
req.end()

▍Выполнение POST-запроса

Вот как выполнить POST-запрос из Node.js:

const https = require('https')
const data = JSON.stringify({
  todo: 'Buy the milk'
})
const options = {
  hostname: 'flaviocopes.com',
  port: 443,
  path: '/todos',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': data.length
  }
}
const req = https.request(options, (res) => {
  console.log(`statusCode: ${res.statusCode}`)
  res.on('data', (d) => {
    process.stdout.write(d)
  })
})
req.on('error', (error) => {
  console.error(error)
})
req.write(data)
req.end()

▍Выполнение PUT-запросов и DELETE-запросов

Выполнение таких запросов выглядит так же, как и выполнение POST-запросов. Главное отличие, помимо смыслового наполнения таких операций, заключается в значении свойства method объекта options.

▍Выполнение HTTP-запросов в Node.js с использованием библиотеки Axios

Axios — это весьма популярная JavaScript-библиотека, работающая и в браузере (сюда входят все современные браузеры и IE, начиная с IE8), и в среде Node.js, которую можно использовать для выполнения HTTP-запросов.

Эта библиотека основана на промисах, она обладает некоторыми преимуществами перед стандартными механизмами, в частности, перед API Fetch. Среди её преимуществ можно отметить следующие:

  • Поддержка старых браузеров (для использования Fetch нужен полифилл).
  • Возможность прерывания запросов.
  • Поддержка установки тайм-аутов для запросов.
  • Встроенная защита от CSRF-атак.
  • Поддержка выгрузки данных с предоставлением сведений о ходе этого процесса.
  • Поддержка преобразования JSON-данных.
  • Работа в Node.js

Установка

Для установки Axios можно воспользоваться npm:

npm install axios

Того же эффекта можно достичь и при работе с yarn:

yarn add axios

Подключить библиотеку к странице можно с помощью unpkg.com:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

API Axios

Выполнить HTTP-запрос можно, воспользовавшись объектом axios:

axios({
  url: 'https://dog.ceo/api/breeds/list/all',
  method: 'get',
  data: {
    foo: 'bar'
  }
})

Но обычно удобнее пользоваться специальными методами:

  • axios.get()
  • axios.post()

Это похоже на то, как в jQuery, вместо $.ajax() пользуются $.get() и $.post().

Axios предлагает отдельные методы и для выполнения других видов HTTP-запросов, которые не так популярны, как GET и POST, но всё-таки используются:

  • axios.delete()
  • axios.put()
  • axios.patch()
  • axios.options()

В библиотеке имеется метод для выполнения запроса, предназначенного для получения лишь HTTP-заголовков, без тела ответа:

  • axios.head()

Запросы GET

Axios удобно использовать с применением современного синтаксиса async/await. В следующем примере кода, рассчитанном на Node.js, библиотека используется для загрузки списка пород собак из API Dog. Здесь применяется метод axios.get() и осуществляется подсчёт пород:

const axios = require('axios')
const getBreeds = async () => {
  try {
    return await axios.get('https://dog.ceo/api/breeds/list/all')
  } catch (error) {
    console.error(error)
  }
}
const countBreeds = async () => {
  const breeds = await getBreeds()
  if (breeds.data.message) {
    console.log(`Got ${Object.entries(breeds.data.message).length} breeds`)
  }
}
countBreeds()

То же самое можно переписать и без использования async/await, применив промисы:

const axios = require('axios')
const getBreeds = () => {
  try {
    return axios.get('https://dog.ceo/api/breeds/list/all')
  } catch (error) {
    console.error(error)
  }
}
const countBreeds = async () => {
  const breeds = getBreeds()
    .then(response => {
      if (response.data.message) {
        console.log(
          `Got ${Object.entries(response.data.message).length} breeds`
        )
      }
    })
    .catch(error => {
      console.log(error)
    })
}
countBreeds()

Использование параметров в GET-запросах

GET-запрос может содержать параметры, которые в URL выглядят так:

https://site.com/?foo=bar

При использовании Axios запрос подобного рода можно выполнить так:

axios.get('https://site.com/?foo=bar')

Того же эффекта можно достичь, настроив свойство params в объекте с параметрами:

axios.get('https://site.com/', {
  params: {
    foo: 'bar'
  }
})

Запросы POST

Выполнение POST-запросов очень похоже на выполнение GET-запросов, но тут, вместо метода axios.get(), используется метод axios.post():

axios.post('https://site.com/')

В качестве второго аргумента метод post принимает объект с параметрами запроса:

axios.post('https://site.com/', {
  foo: 'bar'
})

Использование протокола WebSocket в Node.js

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

Протокол WebSocket поддерживают все современные браузеры.

▍Отличия от HTTP

HTTP и WebSocket — это очень разные протоколы, в которых используются различные подходы к обмену данными. HTTP основан на модели «запрос — ответ»: сервер отправляет клиенту некие данные после того, как они будут запрошены. В случае с WebSocket всё устроено иначе. А именно:

  • Сервер может отправлять сообщения клиенту по своей инициативе, не дожидаясь поступления запроса от клиента.
  • Клиент и сервер могут обмениваться данными одновременно.
  • При передаче сообщения используется крайне малый объём служебных данных. Это, в частности, ведёт к низким задержкам при передаче данных.

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

▍Защищённая версия протокола WebSocket

Существует небезопасная версия протокола WebSocket (URI-схема ws://), которая напоминает, в плане защищённости, протокол http://. Использования ws:// следует избегать, отдавая предпочтение защищённой версии протокола — wss://.

▍Создание WebSocket-соединения

Для создания WebSocket-соединения нужно воспользоваться соответствующим конструктором:

const url = 'wss://myserver.com/something'
const connection = new WebSocket(url)

После успешного установления соединения вызывается событие open. Организовать прослушивание этого события можно, назначив функцию обратного вызова свойству onopen объекта connection:

connection.onopen = () => {
  //...

}

Для обработки ошибок используется обработчик события onerror:

connection.onerror = error => {
  console.log(`WebSocket error: ${error}`)
}

▍Отправка данных на сервер

После открытия WebSocket-соединения с сервером ему можно отправлять данные. Сделать это можно, например в коллбэке onopen:

connection.onopen = () => {
  connection.send('hey')
}

▍Получение данных с сервера

Для получения с сервера данных, отправленных с использованием протокола WebSocket, можно назначить коллбэк onmessage, который будет вызван при получении события message:

connection.onmessage = e => {
  console.log(e.data)
}

▍Реализация WebSocket-сервера в среде Node.js

Для того чтобы реализовать WebSocket-сервер в среде Node.js, можно воспользоваться популярной библиотекой ws. Мы применим её для разработки сервера, но она подходит и для создания клиентов, и для организации взаимодействия между двумя серверами.

Установим эту библиотеку, предварительно инициализировав проект:

yarn init
yarn add ws

Код WebSocket-сервера, который нам надо написать, довольно-таки компактен:

constWebSocket = require('ws')
const wss = newWebSocket.Server({ port: 8080 })
wss.on('connection', ws => {
  ws.on('message', message => {
    console.log(`Received message => ${message}`)
  })
  ws.send('ho!')
})

Здесь мы создаём новый сервер, который прослушивает стандартный для протокола WebSocket порт 8080 и описываем коллбэк, который, когда будет установлено соединение, отправляет клиенту сообщение ho! и выводит в консоль сообщение, полученное от клиента.

Вот рабочий пример WebSocket-сервера, а вот — клиент, который может с ним взаимодействовать.

Итоги

Сегодня мы поговорили о механизмах сетевого взаимодействия, поддерживаемых платформой Node.js, проведя параллели с аналогичными механизмами, применяемыми в браузерах. Нашей следующей темой будет работа с файлами.

Уважаемые читатели! Пользуетесь ли вы протоколом WebSocket в своих веб-приложениях, серверная часть которых создана средствами Node.js?

Протокол передачи гипертекста (HTTP) – это протокол прикладного уровня для распределенных, совместных, гипермедиа информационных систем. Это основа для передачи данных для Всемирной паутины (т.е. Интернета) с 1990 года. HTTP – это общий протокол без протокола состояния, который можно использовать для других целей, а также с использованием расширений его методов запроса, кодов ошибок и заголовков.

Это руководство основано на спецификации RFC-2616, которая определяет протокол, называемый HTTP / 1.1. HTTP / 1.1 является ревизией исходного HTTP (HTTP / 1.0). Основное различие между HTTP / 1.0 и HTTP / 1.1 заключается в том, что HTTP / 1.0 использует новое соединение для каждого обмена запросами / ответами, где в качестве соединения HTTP / 1.1 может использоваться один или несколько обменов запросами / ответами.

Аудитория

Это руководство было подготовлено для выпускников компьютерных наук и веб-разработчиков, чтобы помочь им понять концепции базового и продвинутого уровня, связанные с протоколом передачи гипертекста (HTTP).

Предпосылки

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

Поскольку я не знаком с этим, это статья о протоколе HTTPпримечания
Ссылочная ссылка:
https://mp.weixin.qq.com/s?__biz=MjM5NTEwMTAwNg==&mid=2650215417&idx=1&sn=8b15c2167f617a91c3dc0702db8cecd5&pass_ticket=weF7IZ62U9Y%2B6dqssNfT%2FfPzCAOaQGTVIs3u%2Fz8xi5M7Gq%2Bi6TfCRFxzITBo9Cfk

Введение в HTTP

Протокол HTTP является аббревиатурой от Hyper Text Transfer Protocol (Протокол передачи гипертекста), который основан на передаче протокола TCP / IP (файлы HTML, файлы изображений, результаты запросов и т. Д.). Он не включает передачу пакетов данных (упаковщик), он в основном определяет формат связи между клиентом и сервером и использует порт 80 по умолчанию.

Функции HTTP

  1. Просто и быстро: Когда клиент запрашивает услугу с сервера, необходимо передать только метод запроса и путь. Обычно используются следующие методы запроса: GET, HEAD, PUT, DELETE, POST. Каждый метод определяет различный тип клиент-серверного контакта. Поскольку протокол HTTP прост, размер программы сервера HTTP невелик, поэтому скорость связи высока.
  2. гибкий: HTTP позволяет передавать любой тип объекта данных.
  3. Нет связи: Нет соединения означает ограничение только одним запросом на соединение. После того, как сервер обработал запрос клиента и получил ответ клиента, он отключается. Таким образом, время передачи может быть сэкономлено.
    Так HTTPПолудуплексная связь
    В то же время данные являются односторонним потоком, сервер не может активно передавать данные клиенту. До появления WebSocket это было хорошим решением этой проблемы.
    4Отсутствие состояния: протокол HTTP не имеет состояния. Сам протокол HTTP не сохраняет состояние связи между запросами и ответами. Нет никаких зависимостей между любыми двумя запросами.Интуитивно понятно, что каждый запрос независим, и нет прямой связи с предыдущим запросом и последующим запросом. Сам протокол не сохраняет информацию обо всех предыдущих сообщениях запроса или ответа.Это делается для быстрой обработки большого количества транзакций и обеспечения масштабируемости протокола, а протокол HTTP был разработан так, чтобы быть таким простым.

Разница между GET и POST

  • GET безвреден, когда браузер откатывается, и POST отправляет запрос снова.

  • GET-запросы активно кешируются браузером, а POST — нет, если только они не установлены вручную.

  • Параметры запроса GET полностью сохраняются в истории браузера, в то время как параметры в POST не сохраняются.

  • Параметры, передаваемые в URL для запросов GET, ограничены по длине, в то время как POST не ограничен.

  • Параметры GET передаются через URL, а POST помещается в тело запроса.

Постоянное соединение

** В первоначальной версии протокола HTTP TCP-соединение было отключено для каждого HTTP-сообщения. ** С точки зрения коммуникации в этом году, потому что это была передача всего текста с небольшой емкостью, даже тогда не было особых проблем. Однако из-за популярности HTTP документы часто содержат большое количество изображений. Например, при использовании браузера для просмотра HTML-страницы, содержащей несколько изображений, при отправке запроса на доступ к ресурсам HTML-страницы он также запрашивает другие ресурсы, содержащиеся на HTML-странице. Таким образом,Каждый запрос вызовет ненужное установление и отключение TCP-соединения, что увеличит накладные расходы на связь.

Чтобы решить вышеуказанную проблему с TCP-соединением, HTTP / 1.1 и часть HTTP / 1.0 предложили метод постоянных соединений HTTP (также известный как HTTP keep-alive или повторное использование HTTP-соединения). Характеристики постоянных соединений:Пока ни одно соединение явно не предложено ни на одном конце, состояние соединения TCP сохраняется.

Преимущество постоянного соединения состоит в том, что оно уменьшает дополнительные издержки, вызванные повторным установлением и разъединением TCP-соединений, и снижает нагрузку на стороне сервера. Кроме того, уменьшение части служебных данных позволяет HTTP-запросам и ответам завершаться раньше, что соответственно увеличивает скорость отображения веб-страницы.
В HTTP / 1.1 все соединения по умолчанию постоянны, но не стандартизированы в HTTP / 1.0. Хотя некоторые серверы реализуют постоянные соединения нестандартными способами, серверная сторона может не поддерживать постоянные соединения. Нет сомнений в том, что помимо серверной части клиент также должен поддерживать постоянные соединения.

Pipelining

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

Если вы запрашиваете веб-страницу HTML с 10 изображениями,Постоянные соединения могут завершать запросы быстрее, чем с отдельными соединениями. Конвейерная связь быстрее, чем постоянные соединения.

TCP трехстороннее рукопожатие и четыре волны

TCP — очень сложный протокол, для многих я слишком сложен для начинающих. Когда я смогу понять этот контент, а затем обновить его. Поэтому я поместил ссылку непосредственно для всех, чтобы прочитать.
https://juejin.im/entry/58fe461c570c350058ec7a57
Трехстороннее рукопожатие

Четыре волны
https://juejin.im/post/5a7835a46fb9a063606eb801

Разница между HTTPS и HTTP

Основное различие между HTTPS и HTTP: еще одно шифрование TLS. TLS-шифрование — это асимметричное шифрование. Я до сих пор не понимаю конкретный принцип и поставил ссылку напрямую.
https://juejin.im/post/584b76d3a22b9d0058d5036f
https://zhuanlan.zhihu.com/p/37738632 (рекомендуется от мелкой до глубокой статьи)

Понравилась статья? Поделить с друзьями:
  • Red dot scope instructions инструкция на русском
  • Блок управления теплым полом электрическим инструкция
  • Противовирусные таблетки ранитидин инструкция по применению
  • Сервис мануал для ризографа
  • Инструкция по использованию филлера для волос lador