HTTP для начинающих. Часть 1. Определения

HTTP для начинающих. Часть 1. Определения

27 марта 2022 г.

Как веб-разработчик, я иногда описываю свою работу как «заставить вещи общаться друг с другом через Интернет». HTTP, что означает протокол передачи гипертекста, делает это возможным. Другими словами, HTTP — это метод отправки сообщений из одной программы в другую через Интернет.


В этой статье я расскажу об терминах HTTP, инструментах и ​​структуре HTTP-сообщений. Я использую аналогии и метафоры и объясняю вещи разными способами, пытаясь создать полезные ментальные модели. В [Руководстве по HTTP для начинающих — Часть 2: Ответы] (https://app.hackernoon.com/mobile/URwef1IC4FutwiOmJmPM) я подробно расскажу, как написать код для генерации ответных сообщений HTTP на сервере. После этого в [Руководстве по HTTP для начинающих — Часть 3: Запросы] (https://dev.to/abbeyperini/a-beginners-guide-to-http-part-3-requests-63) я расскажу как генерировать HTTP-запросы в клиенте. Наконец, мы немного повеселимся с нашим приложением и некоторыми бесплатными API, созданными для нас другими людьми в Руководстве по HTTP для начинающих — Часть 4: API.


Введение и оглавление


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


Я не буду объяснять TCP, множество определений слова "протокол», или как работает Интернет. Это общий обзор и руководство по использованию HTTP-сообщений в вашем веб-приложении.


  1. Условия веб-разработки

  1. Термины HTTP, асинхронный JavaScript и инструменты HTTP

  1. Структура запроса

  1. [Методы] (#h-методы)

  1. Заголовки запроса

  1. [Тело запроса] (#h-запрос-тело)

  1. Структура ответа

  1. Коды состояния и сообщения

  1. КОРС

  1. Дополнительные ресурсы

Условия веб-разработки


Во-первых, давайте определим несколько терминов, которые я буду часто использовать. Приложение или прикладная программа — это программное обеспечение, работающее на компьютере. Базовая конфигурация большинства веб-приложений — это клиентское приложение, работающее в браузере, таком как Chrome, Firefox или Safari, и серверное приложение, которое предоставляет услуги и ресурсы для клиента. Таким образом, браузер функционирует как среда выполнения для клиентского или клиентского кода. В JavaScript наиболее распространенной средой выполнения, используемой для серверного или серверного кода, является Node.js. Другими словами, клиент — это часть кода, с которой взаимодействует пользователь — нажимает кнопки или читает информацию на странице в своем браузере. Чтобы получить информацию, которую пользователь хочет прочитать, или получить или обновить информацию после того, как пользователь что-то щелкнет, мой клиент будет общаться с моим сервером, используя HTTP.


Я часто использую «приложение» для обозначения моего клиента, потому что не каждому веб-приложению нужен сервер. Можно иметь веб-приложение только с клиентом, например калькулятор, который может выполнять все свои математические операции, не получая больше информации из другого ресурса. Можно только создать клиент и использовать ресурсы на стороне сервера, созданные другими людьми. Возможно, вы видели термин «бессерверный», который относится к способам создания сервисов и ресурсов, подобных серверу, без самостоятельной сборки сервера. На самом деле бессерверные приложения включают создание клиента, а затем использование таких инструментов, как [AWS] (https://aws.amazon.com/serverless/) или [Netlify] (https://www.netlify.com/products/functions/). ) для написания серверного кода внутри клиента. При необходимости ваш клиент будет использовать этот инструмент для выполнения серверного кода на сервере, созданном и размещенном другими людьми. В целях изучения HTTP в этом руководстве мы сосредоточимся на классической [модели клиент-сервер] (https://en.wikipedia.org/wiki/Client%E2%80%93server_model), которую я описал выше.


Внешний вид: Facebook реагирует на смайлики. Внешний вид: смайлики, показанные сзади в виде маленьких людей, засовывающих свои лица в дыры


Я не буду использовать термины «внешняя часть» и «внутренняя часть», поскольку термины «клиент» и «сервер» более конкретны. Например, серверная часть веб-приложения будет включать не только сервер, но также базу данных и любые другие службы и инструменты, используемые сервером.


API означает интерфейс прикладного программирования. Он позволяет двум приложениям, таким как клиент и сервер, взаимодействовать друг с другом. Если сервер — это весь ресторан, API — официант, меню — список методов, которые предоставляет API, а голодный клиент — клиент. Я расскажу о стандартизированных форматах для API и многом другом в части 4.


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


Термины HTTP, асинхронный JavaScript и инструменты HTTP


Существуют разные версии HTTP. HTTP/2 более оптимизирован и безопасен, чем HTTP/1.1, и его использует около половины веб-сайтов. Есть даже HTTP/3, разработанный Google. Возможно, вы уже видели http:// и https:// в своих URL-адресах и предупреждениях браузера о безопасности. Сообщения HTTP шифруются при отправке по HTTPS и не шифруются при отправке по HTTP.


Есть несколько библиотек, которые вы можете использовать для отправки HTTP-сообщений. Например, curl можно использовать из командной строки. Все они используют HTTP, поэтому необходимая им информация одинакова. Отличие заключается в том, где вы можете их использовать, в синтаксисе для создания HTTP-сообщений, предоставляемых ими параметрах и используемом протоколе (например, HTTP против HTTPS, HTTP/1.1 против HTTP/2). Более надежные библиотеки будут делать дополнительные вещи.


HTTPS GO BRRR - jacked shibe с надписью HTTPS, sad shibe с меткой HTTP


При просмотре HTTP-библиотек JavaScript вы можете встретить термин AJAX или Ajax. Это означает асинхронный JavaScript и XML. Проще говоря, асинхронный код работает не по порядку. Отправка сообщения через Интернет и получение обратно сообщения требует времени. Асинхронный код может по существу приостановить выполнение до тех пор, пока данные не будут получены, а затем возобновить выполнение с того места, где оно было остановлено. XML означает расширяемый язык разметки. Это как HTML, но без предопределенных тегов. Это один из форматов, используемых для структурирования данных, которые вы можете отправить в HTTP-сообщении. Ajax может относиться к использованию HTTP с JavaScript, даже если сообщение не содержит данных или данные не структурированы с помощью XML.


Когда вы пишете JavaScript и запускаете его в браузере, у вас есть доступ ко множеству встроенных инструментов. Трудно представить создание веб-сайта без веб-API, таких как HTML DOM и URL. Долгое время единственным доступным HTTP Web API был XMLHttpRequest или XHR. Поскольку это была библиотека Ajax, она, наконец, позволила веб-страницам извлекать данные из базы данных без необходимости обновления всей страницы.


Более современная версия, поддерживаемая всеми браузерами, кроме IE, — это [Fetch] (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). Поддержка Fetch была включена в последнюю версию Node.js в январе 2022 года. Она основана на XHR, предоставляя интерфейсы (ожидаемые форматы) для обеих половин. HTTP-разговора и там, где XHR использует обратные вызовы, Fetch использует обещания.


Обратные вызовы и промисы — довольно большие темы. По сути, функция обратного вызова передается в качестве аргумента асинхронной (асинхронной) функции. После того, как асинхронная функция получает то, что ей нужно, выполняется функция обратного вызова. Обещания, с другой стороны, являются объектами, возвращаемыми асинхронными функциями. У них есть три состояния: ожидание, выполнение и отклонение. Асинхронные функции, которые возвращают промисы, могут быть объединены в цепочку с .then() и .catch(). Таким образом, разработчик может передать возвращенное выполненное обещание функции в .then() или передать возвращенное отклоненное обещание в .catch() и обработать ошибку. Javascript также имеет синтаксис async/await, который использует промисы без необходимости явно создавать объекты промисов или передавать их в цепочку. (Тем не менее, вы можете связать их, если хотите.) Другие функции могут вызывать await asyncFunction() и ждать результата, прежде чем продолжить выполнение. Часто результат вызова функции устанавливается в переменную, которая будет использоваться позже. У меня есть примеры кода в части 3 и дополнительные ресурсы для изучения этих тем на конец этой статьи.


Кермит потягивает чай, подпись: «Раньше я давал обещания, теперь я просто жду свои асинхронные функции»


Наконец, есть такие пакеты, как [Axios] (https://github.com/axios/axios). Axios не только предоставляет интерфейсы и использует промисы, но также позволяет разработчику выполнять как HTTP-запросы на стороне клиента в браузере с использованием XHR, так и HTTP-запросы на стороне сервера в Node.js. Он также предоставляет больше возможностей и форматирует ваши сообщения для вас.


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


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


Если мы говорим, что клиент и сервер разговаривают, две половины разговора — это запрос и ответ. Используя HTTP-запрос, клиент запрашивает что-то с сервера.


Каждый запрос требует некоторой информации для работы:


  • Метод: Метод сообщает серверу, что от него хочет клиент.

  • URL-адрес: URL-адрес сообщает инструменту HTTP, куда отправить запрос.

  • Протокол: устанавливается используемым инструментом HTTP.

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

URL-адрес в сообщении HTTP-запроса работает так же, как когда вы вводите URL-адрес для перехода на веб-страницу в своем браузере. URL-адрес также можно использовать для отправки дополнительной информации — я объясню больше об URL-адресах и о том, как их использовать, в [части 2] (https://app.hackernoon.com/mobile/URwef1IC4FutwiOmJmPM).


Также есть необязательная часть:


  • Тело: если запрос использует метод, который отправляет данные на сервер, данные включаются в тело сразу после заголовков.

Таким образом, сообщение HTTP-запроса будет выглядеть примерно так:
квадрат с POST https://dev.to/hasCar/HTTP/2 в красном поле, Accept: application/json Content-type: application/ json Content-length: 700 в желтом поле, белый пробел и '{"name":"John", "car":true}' в синем поле внутри него


Первая строка, показанная здесь красным цветом, содержит метод, URL-адрес и протокол. Вторая, желтая часть содержит все заголовки. Есть пустая строка, а затем, если есть тело, оно идет в конце, здесь показано синим цветом.


Методы


Самый простой способ объяснить методы — сопоставить их с аббревиатурой постоянного хранилища, CRUD. CRUD означает создание, чтение, обновление и удаление. Вы можете думать об этом с точки зрения базы данных, использующей SQL:


Создать = ВСТАВИТЬ


Читать = ВЫБРАТЬ


Обновление = ОБНОВЛЕНИЕ


Удалить = УДАЛИТЬ


Вы можете думать об этом с точки зрения пользовательского интерфейса приложения:


Создать = пользователи, создающие новый пост


Читать = пользователи, просматривающие свою ленту новостей


Обновление = пользователи, редактирующие сообщение


Удалить = пользователи удаляют сообщение


Для HTTP-запросов:


Создать = ОТПРАВИТЬ


Читать = ПОЛУЧИТЬ


Обновить = ПОСТАВИТЬ или ИСПРАВИТЬ


Удалить = УДАЛИТЬ


Примечание. Есть [больше методов, которые я не рассмотрел] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods), потому что я их еще не использовал.


POST отправляет данные на сервер и приводит к изменению. Это требует тела.


GET запрашивает данные с сервера для отправки обратно через ответ. У него нет тела.


PUT отправляет данные на сервер для создания нового ресурса или замены существующего ресурса. Это требует тела.


PATCH отправляет данные на сервер для обновления части существующего ресурса. Это требует тела.


DELETE запрашивает удаление ресурса. Он может иметь тело, если информация, необходимая для идентификации удаляемого ресурса, не содержится в URL-адресе.


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


Чарли из «Всегда солнечно» разглагольствует о Пепе Сильвии со стеной, обтянутой красной лентой, и почтой позади него, с подписью «Я объясняю заголовки HTTP»


Существует много заголовков HTTP-запросов. Если сервер — концерт, а HTTP-запрос — посетитель, заголовки похожи на билет и идентификатор посетителя. Заголовок Origin сообщает серверу, откуда пришел запрос. Заголовок Accept сообщает серверу, какой формат сервер должен использовать для своего ответа. Заголовок Content-Type сообщает серверу, какой формат использует тело запроса. Некоторые из них автоматически создаются библиотекой HTTP. Некоторые, например заголовки аутентификации, диктуются сервером. Я расскажу об аутентификации в части 3, когда буду запрашивать данные из API, для которого требуется ключ. Многие заголовки вы найдете как в запросе, так и в ответе. Если спецификация HTTP относится к заголовку как к заголовку запроса, она предоставляет информацию только о контексте запроса. Разработчики будут ссылаться на заголовки, включенные в запрос, как на заголовки запроса в разговоре, даже если они также могут использоваться в качестве заголовка ответа и наоборот.


Тело запроса


Тела сообщений HTTP могут быть упакованы в несколько стандартизированных форматов передачи данных. Форматы называются [типы мультимедиа или типы MIME] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types), и их много. XML и JSON — это два, которые вы будете видеть чаще всего. Оба они создают тела с одним ресурсом, что означает, что они являются одним файлом в теле сообщения HTTP.


JSON означает нотацию объектов JavaScript. Он имеет стандартный синтаксис, который создает файлы меньшего размера. Встроенные методы JavaScript легко превращают строку JSON в допустимые объекты JavaScript. JSON может быть закодирован только в UTF-8 и имеет типы. XML не имеет типов, может сохранять исходную структуру данных, поддерживает несколько типов кодирования, более безопасен и может отображаться в браузере без каких-либо изменений. XML требует работы для преобразования в JavaScript, и его труднее читать людям, но легче читать машинам. XML против JSON, как JSON стал наиболее широко используемым форматом передачи данных HTTP и какие другие форматы все еще существуют — это огромная тема. [Синопсис Twobithistory] (https://twobithistory.org/2017/09/21/the-rise-and-rise-of-json.html) запустит вас в кроличью нору. Я буду использовать JSON и расскажу о его синтаксисе и встроенных методах JavaScript в части 2 и части 3.


[ ![Муфаса: Смотри, Симба, все, к чему прикасается свет, — это JSON. Симба: Вау. Но как насчет этого темного места? Муфаса: Это XML. Ты никогда не должен туда ходить, Симба практический dev/image/fetch/s--_3zE6x5v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9g3o5r5y2s22ijct9duv.jpg)


Тип MIME и кодировка символов, используемые в теле запроса, объявляются в заголовке запроса Content-Type, поэтому сервер знает, как декодировать и обрабатывать данные в теле запроса. Содержимое XML будет иметь application/xml в заголовке. Содержимое JSON будет иметь application/json.


Лучшим примером тела с несколькими ресурсами являются данные, отправленные из HTML-формы на веб-странице. В заголовке Content-Type будет multipart/form-data. Вместо одного тела есть несколько тел, по одному для каждой части формы, каждое со своим собственным заголовком Content-Type. Таким образом, введенные пользователем данные могут быть отправлены на сервер вместе со свойствами HTML-элемента, который он использовал для их ввода. В результате, если у вас есть <input> с таким свойством, как name="first_name", тело запроса будет включать "name='first_name'" с именем, которое пользователь ввел в <input> .


Структура ответа


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


  • Протокол: устанавливается используемым инструментом HTTP.

  • Код состояния: набор цифр, который покажет вам, как прошел процесс от запроса до ответа.

  • Сообщение о состоянии: удобочитаемое описание, которое расскажет вам, как прошел процесс от запроса до ответа.

  • Заголовки: Предоставляет клиенту больше информации о самом ответе.

Также есть необязательная часть:


  • Тело: если ответ содержит данные с сервера, они будут включены сюда. Тела запросов и ответов используют одинаковые форматы.

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


Квадрат с HTTP/2 200 OK в красном поле, Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST Content-type: application/json в желтом поле, a белый пробел и '{"name":"John", "car":true}' в синем прямоугольнике внутри него


Первая строка, показанная здесь красным цветом, содержит протокол, код состояния и сообщение о состоянии. Далее в желтом разделе находятся заголовки. За заголовками следует одна пустая строка. Наконец, если есть данные для отправки обратно, есть тело, показанное здесь синим цветом.


Коды состояния и сообщения


Вы сталкивались с кодами статуса раньше при использовании Интернета. Все видели «404 Not Found», и вы, возможно, видели «403 Forbidden». Тот, на который вы будете надеяться при написании HTTP-запросов, — это успешный «200 OK». Те, которые вы не хотите видеть при написании кода на стороне клиента, находятся в 400-х, например «400 Bad Request» и «405 Method Not Allowed». Проблемы с сервером будут в пределах 500, например «500 Внутренняя ошибка службы» или «503 Служба недоступна».


Backend передает Frontend заметку в классе. Фронтенд оборачивается, хмурясь. В примечании говорится: «Внутренняя ошибка сервера 500»


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


Если вы предпочитаете узнавать свои коды состояния и сообщения, сопровождаемые изображениями животных, проверьте [HTTP Cats] (https://http.cat/) и [HTTP Status Dogs] (https://httpstatusdogs.com/417- ожидание не оправдалось).


КОРС


Поскольку большинство, но не все [заголовки CORS] (https://developer.mozilla.org/en-US/docs/Glossary/CORS) являются заголовками запросов, давайте углубимся в CORS здесь.


[CORS] (https://www.codecademy.com/article/what-is-cors) означает совместное использование ресурсов между источниками. По умолчанию браузеры и серверы, на которых работает JavaScript, используют CORS для блокировки запросов от клиента, источник которого отличается от сервера, в целях безопасности. Целью CORS является защита клиента и сервера от выполнения вредоносного кода, содержащегося в HTTP-запросе, и предотвращение кражи данных с сервера.


Для большинства браузеров источник относится к хосту, протоколу и порту, если он указан. Хост — это часть URL-адреса после www. и перед /. Таким образом, для www.google.com хостом является google.com. Протокол HTTP против HTTPS и HTTP/1.1 против HTTP/2. Порт будет 3000 в http://localhost:3000.


Прежде чем ваш исходный запрос будет отправлен, HTTP отправит предварительный запрос с некоторыми заголовками, такими как источник и метод, чтобы проверить, является ли запрос, который вы хотите сделать, безопасным. Затем сервер отправляет ответ предварительной проверки с заголовками CORS, такими как Access-Control-Allow-Origin и Access-Control-Allow-Methods, которые сообщают браузеру, разрешен ли исходный запрос. Это когда запрос будет заблокирован CORS, если он будет.


Твит Эбби Перини «CORS пишется заглавными буквами, потому что рано или поздно вы начнете кричать об этом».


Вы можете указать, разрешает ли сервер запросы CORS, только если вы пишете серверный код. Например, ответ сервера будет включать заголовок Access-Control-Allow-Origin, в котором перечислены источники, которые могут получить запрос. Если вашего источника нет в списке в заголовке Access-Control-Allow-Origin в ответе, ваш запрос будет заблокирован, и вы не сможете изменить это, если не напишите код, который отправляет ответы.


Если сервер ослабляет ограничения CORS, он обычно заменяет его обязательной проверкой подлинности или использует заголовок Access-Control-Allow-Methods, чтобы ограничить методы запроса только GET. Аутентификацию можно отправить в заголовках или URL (подробнее об этом в части 3).


Однако, даже если сервер разрешает запросы CORS, ваш браузер блокирует запрос CORS в коде на стороне клиента. Вы можете обойти это, запросив данные с сервера, используя свой собственный сервер, а затем передав то, что вам нужно, из ответа вашему клиенту.


Дополнительные ресурсы


Если вы только начинаете знакомиться с асинхронным Javascript, я настоятельно рекомендую бросить все и посмотреть два видео прямо сейчас: Филип Робертс, «Что, черт возьми, это цикл событий?» и [«In The Loop» Джейка Арчибальда] (https://youtu.be/cCOL7MC4Pl0).


Обратные вызовы и промисы — сложные понятия, и я объяснил их очень быстро. Я по-настоящему понял их только после того, как писал с ними код каждый день в течение нескольких месяцев. В ваших интересах узнать об обратных вызовах, прежде чем переходить к промисам, поскольку объекты промисов и цепочка создают свои собственные проблемы. Вот еще несколько ресурсов, которые должны помочь вам понять их:







Заключение


Было много определений, прежде чем мы добрались до кода! HTTP-сообщения сложны, но они также являются основой веб-приложений. Если вы остались в замешательстве или вам нужны дополнительные ресурсы по теме, которую я затронул, не стесняйтесь оставлять комментарии ниже.


Затем ознакомьтесь с [Руководство по HTTP для начинающих — Часть 2: Ответы] (https://app.hackernoon.com/mobile/URwef1IC4FutwiOmJmPM) и [Руководство по HTTP для начинающих — Часть 3: Запросы] (https://dev .to/abbeyperini/a-beginners-guide-to-http-part-3-requests-63)!


Вскоре:


  • Руководство для начинающих по HTTP — Часть 4: API

Также опубликовано здесь



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE