HTTP: Протокол, который должен знать каждый веб-разработчик (Часть 1)
() translation by (you can also view the original English article)
HTTP означает Hypertext Transfer Protocol (* протокол прикладного уровня для "переговоров" о доставке Web-сервером документа Web-браузеру. НТТР служит также для передачи XML-файлов, VoiceXML , WML , потокового видео и аудио. Обычно использует порт 80, а в качестве протокола транспортного уровня - TCP . Основной протокол WWW , определённый в RFC 1945 (НТТР 1.0), 2068 и 2616 (НТТР 1.1), с помощью которого HTML-документы пересылаются по Интернету от узла к узлу. НТТР поддерживает постоянные (передача многих объектов) и непостоянные соединения (передача одного объекта веб-документа за сеанс обмена между клиентом и сервером), а также два метода идентификации пользователей: авторизацию и объекты (файлы) cookie. Здесь и далее прим. пер.). Это протокол уровня приложений без запоминания состояния (* stateless; не предусматривает сохранения информации о сессии пользователя; каждая передача данных рассматривается как новая сессия) для общения распределенных информационных систем; также является основой современной Всемирной паутины. Являясь веб-разработчиками, мы все должны иметь четкое представление об этом протоколе.
Давайте рассмотрим этот мощный протокол через призму веб-разработчика. Мы разберем эту тему в двух частях руководства. В первой мы рассмотрим основы и дадим общее представление о заголовках запроса и ответа. В последующей части мы рассмотрим специальные вопросы технологии HTTP, а именно: кэширование, реализацию соединения и аутентификацию (* в системе компьютерной безопасности – процесс, позволяющий установить, что пользователь или компьютер (сервер), пытающийся получить интерактивный доступ к определенной категории информации, компьютерной системе, вычислительной сети или электронной почте, действительно тот, за кого себя выдает).
Хотя я упомяну некоторые детали насчет заголовков, за исчерпывающим описанием вам лучше будет обратиться к RFC (RFC 2616). Я буду ссылаться на определенные части документа RFC на протяжении статьи.
Основы HTTP
HTTP позволяет общаться системам с различной архитектурой и конфигурацией сети (* включает в себя конкретный состав оборудования ЛВС, схему его соединения и сетевое ПО).
Это возможно благодаря тому, что этот протокол предъявляет самые общие требования к системам и не сохраняет состояние между обменами различными сообщениями.
По этой причине HTTP считается протоколом без запоминания состояния. Для транспортировки сообщений обычно служит протокол TCP (* Transmission Control Protocol; протокол управления передачей, протокол TCP широко используемый в Internet протокол транспортного уровня из набора TCP/IP. Гарантирует доставку передаваемых пакетов данных в нужной последовательности, но трафик при этом может быть весьма неравномерен, так как пакеты испытывают всевозможные задержки), однако может использоваться любой другой подходящий механизм для транспортировки сообщений (* например, QUIC (Quick UDP Internet Connections) – экспериментальный интернет-протокол, разработанный Google в конце 2012 года). Портом по умолчанию для HTTP является порт 80, но могут использоваться и другие порты.



Также можно добавлять и отправлять специализированные (* связанные с (конкретным) применением, в отличие от стандартизованных в RFC заголовков) собственные заголовки к серверу (* и от сервера).
Обмен сообщениями между клиентом и сервером идет по схеме «запрос-ответ». Клиент начинает общение, отправляя сообщение запроса HTTP, в ответ на которое сервер отсылает сообщение ответа HTTP. Мы рассмотрим эту основополагающую пару в следующем разделе.
Текущая версия протокола – HTTP/1.1, в которой добавлены дополнительные возможности по сравнению с предыдущей – HTTP/1.0. Среди них, на мой взгляд, наиболее важными являются: долговременные соединения (* persistent connections; передача в одном TCP-соединении нескольких объектов, причем время существования соединения определяется при конфигурировании веб-службы), кодирование передачи данных типа "chunked" (* по частям) (* chunked transfer-coding; механизм передачи данных в протоколе передачи гипертекста (HTTP), позволяющий надежно доставлять данные от сервера клиенту (чаще всего клиентскому web-браузеру) без необходимости заранее знать точный размер всего тела HTTP-сообщения. Это достигается разбиением сообщения на небольшие части (chunks), а затем передачей каждой части с указанием только её размера (в шестнадцатеричном виде). Окончание передачи сообщения определяется наличием последней части с нулевой длиной. Такой механизм позволяет передать динамически сформированные объекты, для которых нельзя заранее определить размер. Он стал доступен только начиная с HTTP версии 1.1 (HTTP/1.1). Без механизма сhunked transfer encoding с каждым HTTP-пакетом необходимо указывать заголовок Content-Length, чтобы клиент мог найти конец передаваемого сообщения) и тонко гранулированные (* метафорическое определение (обозначение) процесса или системы для работы с небольшими объектами, например, отдельными битами и байтами, а не с относительно большими объектами, например файлами или записями) заголовки, при помощи которых задаются директивы для механизма кэширования. Мы коротко рассмотрим эти возможности в этой части; детальное рассмотрение будет во второй.
URL-адреса
В основе коммуникации во Всемирной паутине лежат сообщения запросов, которые пересылаются при помощи URL-адресов (* Uniform Resource Locator - унифицированный указатель [местонахождения информационного] ресурса). Уверен, что вы уже знакомы с ними, однако для полноты картины мы их кратко рассмотрим. По своей структуре URL-адреса просты; в ней выделяют следующие компоненты:



Обычно используется протокол HTTP
, однако им также может быть и HTTPS
(* HTTP Secure; протокол защищенной передачи гипертекстов. Расширение протокола НТТР; совместим с НТТР, но использует порт 443 протокола TCP) для обеспечения связи по защищенному каналу. Портом по умолчанию является 80
, однако его можно явно задать, как показано выше. Путь к объекту – это локальный путь к ресурсу на сервере.
Методы
Также в их распоряжении имеются прокси для отладки веб-приложений, например, Fiddler (* работает с трафиком между вашим компьютером и удаленным сервером и позволяет просматривать и менять его) (для Windows) и Charles Proxy (для OSX).
URL-ссылки идентифицируют определенный сервер, с которым мы хотим наладить обмен сообщениями, однако действие, которое должно быть выполнено на сервере, указывается при помощи методов HTTP. Естественно, что клиент хотел бы выполнить некоторые действия (* методы) на сервере. В HTTP стандартизированы несколько, благодаря которым можно реализовать самые необходимые возможности; эти методы универсальны для всех видов приложений.
Эти методы запроса перечислены ниже:
- GET: для получения существующего ресурса. В URL-адресе содержится вся необходимая информация для определения местонахождения и возвращения ресурса сервером.
- POST: для создания нового ресурса. Запросы по методу POST обычно содержат данные для создания нового ресурса.
- PUT: для обновления существующего ресурса. В содержимом могут находиться обновленные данные для ресурса.
- DELETE: для удаления существующего ресурса.
Выше перечисленные методы наиболее распространены, и большинство инструментов и фреймворков предоставляют функции для работы с этими методами. Иногда PUT
и DELETE
рассматриваются как специализированные версии метода POST
и могут быть оформлены в виде запросов по методу POST
с данными, определяющими точное действие: создать, обновить, удалить.
Также HTTP поддерживает некоторые реже используемые методы:
- HEAD: подобен GET, однако не передается тело сообщения. Он используется для получения заголовков определенного ресурса с сервера, обычно чтобы проверить при помощи временной отметки, не изменился ли ресурс.
- TRACE: используется для получения от сервера информации о «прыжках» (* ближайший маршрутизатор, маршрутизатор, находящийся на расстоянии одного прыжка), через которые прошел запрос. Каждый промежуточный прокси-сервер (* программа кэширования ответов на посылаемые в Internet или в WWW запросы клиентских частей приложений, работающая на прикладном уровне. Копии полученных Web-страниц, файлов и т. д. хранятся какое-то время на сервере, и при получении последующих аналогичных запросов proxy-сервер сам высылает имеющиеся копии, что позволяет сократить время отклика и объем сетевого трафика. Кроме того, proxy-сервер может фильтровать запросы, закрывая доступ к сайтам определенного типа, обеспечивая таким образом информационную безопасность и возможности административного контроля; средства, защищающие локальную сеть от несанкционированного доступа через интернет; программный агент, действующий от имени пользователя) или шлюз (* сетевое устройство или компьютер, осуществляющие связь между двумя различными, использующими разные коммуникационные протоколы (communications protocol), компьютерными сетями или мэйнфреймом и сетью, соответственно могут выполнять преобразование одного набора протоколов в другой) при этом будут заносить свой IP-адрес (* используется для идентификации узла в сети и для определения информации маршрутизации; состоит из идентификатора сети (network ID) и идентификатора хоста (host ID), присвоенного сетевым администратором) или имя DNS (* механизм, используемый в сети и устанавливающий соответствие между числовыми IP-адресами и текстовыми именами) в поле
Via
заголовка. Его можно использовать с диагностическими целями. - OPTIONS: для получения поддерживаемых сервером возможностей. На стороне клиента его можно использовать для изменения запроса в зависимости от возможностей, поддерживаемых сервером.
Коды состояния (* значение, возвращаемой процедурой или функцией, показывающее состояние устройства или процесса)
Имея URL-адреса и методы, клиент может инициировать запросы к серверу. В ответ сервер присылает ответы с кодами состояния и содержимым сообщений. Код состояния – важный компонент сообщения; он указывает клиенту, как интерпретировать ответ сервера. В спецификации (* документ, который в идеале содержит полное, точное, детальное описание функций и/или параметров (например, продукта, программы, стандарта и т. п.), а также, возможно, процедур, позволяющих определить, соответствует ли продукт данной спецификации) HTTP устанавливаются определенные диапазоны чисел для конкретных типов ответов:
1xx: Информация о процессе передачи
Всем клиентам HTTP/1.1 необходимо, чтобы в сообщении был заголовок
Transfer-Encoding.
Этот класс кодов появился в HTTP/1.1 и используется просто для предварительного общения клиента и сервера. Сервер может отослать в ответ на сообщение клиента с заголовком Expect: 100-continue
ответ (* например, 100 Continue (Продолжать) (код и соответствующая поясняющая фраза)), инструктируя клиента продолжить отправление оставшейся части запроса или проигнорировать сообщение, если тот уже ее отослал. При работе через HTTP/1.0 сообщения с такими кодами должны игнорироваться (* в версии 1.1 клиент должен быть готов принять этот класс сообщений как обычный ответ, но серверу отправлять что-либо не нужно).
2xx: Информация об успешном принятии и обработке запроса клиента
Коды этого класса сообщают клиенту, что его запрос успешно обработан. Наиболее часто встречается код (* и соответствующая поясняющая фраза) 200 OK. На запросы по методу GET
сервер отсылает в ответ запрашиваемые данные в теле сообщения. Ниже перечислены некоторые более редко используемые коды (* и соответствующие фразы):
- 202 Accepted (* Принято): запрос был принят на обработку (* но она не завершена), но в ответе может не быть запрашиваемых данных. Этот вариант полезен для асинхронной обработки на стороне сервера. Сервер может решить отослать информацию для мониторинга (* непрерывный во времени или периодический процесс сканирования состояния каких-либо ресурсов (например, информационных) с целью сбора данных, контроля, управления и/или содержательного анализа).
- 204 No Content (* Нет содержимого): тело сообщения не передается.
- 205 Reset Content (* Сбросить содержимое): клиент должен сбросить (* вернуть исходные значения) введенные пользователем данные (* тела сообщения сервер при этом не передает и документ обновлять не обязательно).
- 206 Partial Content (* Частичное содержимое): указывает, что в ответе содержится только часть ресурса. Клиент может присылать дополнительные заголовки, при помощи которых указывается точный диапазон запрашиваемого ресурса и информация о сроке действия контента.
3xx: Перенаправление
404 сообщает, что запрашиваемый ресурс не существует на сервере.
Этот код указывает клиенту, что необходимо будет выполнить дополнительное действие. Самый распространенный вариант – выполнение запроса по другому URL-адресу (* указанному в дополнительном заголовке Location) для получения запрашиваемого ресурса.
- 301 Moved Permanently (* Постоянно перемещен): запрошенный объект был окончательно перенесен на новый URL.
- 303 See Other (* Смотреть другой): запрошенный объект временно перенесен на новый URL. Временный URL указывается в заголовке
Location
ответа. - 304 Not Modified (* Не модифицирован): сервер обнаружил, что ресурс не был изменен и клиенту следует использовать копию из кэша. Это реализуется за счет того, что клиент отсылает определенное значение (хэш-значение содержимого) в заголовке
ETag
(Entity Tag). Сервер сравнивает это значение со своим собственным токеном (* средство идентификации) для запрашиваемого ресурса на наличие изменений.
4xx: Информация об ошибках со стороны клиента
Эти коды используются, когда сервер считает, что клиент допустил ошибку: будь то ошибочный запрос или же запрос недоступного для клиента ресурса. Наиболее популярное сообщение в данном случае - 404 Not Found (* Не найден), значение которого, думаю, все знают. 404 сообщает, что запрашиваемый ресурс не существует на сервере. Некоторые остальные коды (* и соответствующие фразы) этого класса перечислены ниже:
- 400 Bad Request (Испорченный Запрос): в запросе обнаружена ошибка.
- 401 Unauthorized (* Несанкционированный доступ): для осуществления запроса необходима аутентификация. Клиент может повторно выполнить запрос, добавив заголовок
Authorization
. Если клиент уже использовал этот заголовок, то это значит, что были указаны ошибочные для успешной аутентификации данные. - 403 Forbidden (* Запрещено): сервер отказал клиенту в доступе к указанному ресурсу.
- 405 Method Not Allowed (* Метод не допустим): в строке запроса использовался недопустимый метод HTTP или же сервер не поддерживает этот метод.
- 409 Conflict (* Конфликт): сервер не смог выполнить зарос, поскольку клиент попытался изменить ресурс, временная отметка которого не совпадает с таковой клиента. В большинстве случаев конфликтная ситуация возникает при совместном редактировании ресурса с помощью запросов по методу PUT.
5xx: Информация об ошибках со стороны сервера
Этот тип кодов используется для сообщения о неуспешном выполнении операции по вине сервера. Наиболее часто встречающийся код об ошибке (* и соответствующая поясняющая фраза) – 500 Internal Server Error (* Внутренняя ошибка сервера; любая внутренняя ошибка сервера, которая не входит в рамки остальных ошибок класса). Некоторые остальные коды (* и соответствующие поясняющие фразы) этого класса включают:
- 501 Not Implemented (* Не реализовано): сервер на данный момент не поддерживает возможностей, необходимых для обработки запроса.
- 503 Service Unavailable (* Сервис недоступен): сервер не имеет возможности обрабатывать запросы по техническим причинам или перегружен. Обычно сервер даже не будет отвечать, и запрос превысит лимит времени ожидания от сервера (* timeout; истечение времени ожидания события (обычно задается для операций с периферийными устройствами), по которому возникает и обрабатывается, например, ошибочная ситуация (timeout error)).
Формат HTTP-сообщений
На данный момент мы выяснили, что URL-адреса, методы и коды состояния – это фундаментальные компоненты пары HTTP запрос/ответ.



Теперь давайте рассмотрим содержимое этих сообщений. В спецификации HTTP определяется следующая общая структура сообщений запроса и ответа:
1 |
message = <start-line> |
2 |
*(<message-header>) |
3 |
CRLF |
4 |
[<message-body>] |
5 |
|
6 |
<start-line> = Request-Line | Status-Line |
7 |
<message-header> = Field-Name ':' Field-Value |
Размещение пустой строки между заголовками и телом сообщения является обязательным. В сообщении может содержаться один или несколько заголовков, среди которых условно (* согласно контексту) можно выделить:
- общие заголовки (general headers; применимы для сообщений и запроса, и ответа).
- заголовки запроса.
- заголовки ответа.
- заголовки тела объекта (entity headers).
В теле сообщения могут содержаться все данные сообщения или оно может быть разбито на части, если используется кодирование передачи типа «chunked» (Transfer-Encoding: chunked).
Всем клиентам HTTP/1.1 необходимо, чтобы в сообщении был заголовок Transfer-Encoding.
Общие заголовки
Имеется несколько заголовков (общие заголовки), которые используются и в сообщениях запроса, и в сообщениях ответа:
1 |
|
2 |
general-header = Cache-Control |
3 |
| Connection |
4 |
| Date |
5 |
| Pragma |
6 |
| Trailer |
7 |
| Transfer-Encoding |
8 |
| Upgrade |
9 |
| Via |
10 |
| Warning |
Мы уже знакомы с некоторыми из этих заголовков (Via
и Transfer-Encoding
). Мы рассмотрим Cache-Control
и Connection
во второй части.
Код состояния – важный компонент сообщения; он указывает клиенту, как интерпретировать ответ сервера.
- Заголовок
Via
используется в сообщениях, передаваемых по методу TRACE, и обновляется всеми промежуточными прокси и шлюзами. - Заголовок
Pragma
считается специализированным заголовком и может быть использован для включения в сообщение связанных с конкретной реализацией приложения заголовков. Наиболее часто используется директиваPragma: no-cache
, которая является эквивалентомCache-Control: no-cache
версии HTTP/1.1. Этот заголовок будет рассмотрен во второй части руководства. - Заголовок
Date
используется для добавления времени создания сообщений запроса/ответа. -
Upgrade
используется для переключения протоколов и позволяет осуществить плавный переход на использование нового протокола. -
Transfer-Encoding
обычно используется для разбиения ответа на меньшие части при помощи директивыTransfer-Encoding: chunked.
Этот заголовок впервые появился в версии HTTP/1.1; позволяет реализовать потоковую передачу данных ответа клиенту (* перемещение данных по частям, малыми порциями) (в отличие от пересылки копии данных целиком).
Заголовки для тела сообщения
В сообщениях запроса и ответа также могут использоваться заголовки для тела объекта, чтобы передать мета-информацию о содержимом сообщения (тело сообщения/объекта). Этот тип заголовков включает:
1 |
entity-header = Allow |
2 |
| Content-Encoding |
3 |
| Content-Language |
4 |
| Content-Length |
5 |
| Content-Location |
6 |
| Content-MD5 |
7 |
| Content-Range |
8 |
| Content-Type |
9 |
| Expires |
10 |
| Last-Modified |
При помощи всех заголовков с префиксом Content-
передается информация о структуре, кодировании и размере тела сообщения. Некоторые из этих заголовков должны присутствовать, если в сообщении имеется содержимое.
Благодаря заголовку Expires
указывается срок, по истечении которого тело сообщения считается устаревшим. Интересно то, что при указании значения "never expires" этот срок равен одному году. При помощи заголовка Last-Modified
указывается время последней модификации файла.
Также можно добавлять и отправлять специализированные собственные заголовки к серверу (* и от сервера); согласно протоколу HTTP они будут рассматриваться как заголовки объекта.
Эта возможность – механизм расширения полей заголовка (* позволяет вводить дополнительные поля заголовка объекта (entity-header fields), не изменяя протокол, но эти поля могут быть и не распознаны получателем. Получатель должен игнорировать нераспознанные поля заголовка, а прокси-сервер должен просто пересылать их без изменений), и в некоторых реализациях приложений для коммуникации могут использоваться именно эти специальные заголовки. Хотя HTTP поддерживает специализированные заголовки, в первую очередь его интересуют заголовки ответа и запроса, которые мы и будем рассматривать далее.
Формат сообщений запроса
Общая структура сообщения запроса такая же, как и выше, однако строка запроса выглядит следующим образом:
1 |
Request-Line = Method SP URI SP HTTP-Version CRLF |
2 |
Method = "OPTIONS" |
3 |
| "HEAD" |
4 |
| "GET" |
5 |
| "POST" |
6 |
| "PUT" |
7 |
| "DELETE" |
8 |
| "TRACE" |
SP
– пространственный разделитель между лексемами. На месте HTTP-Version
указывается "HTTP/1.1", и затем идет переход на новую строку. Таким образом, типичное сообщение запроса может выглядеть следующим образом:
1 |
GET /articles/http-basics HTTP/1.1 |
2 |
Host: www.articles.com |
3 |
Connection: keep-alive |
4 |
Cache-Control: no-cache |
5 |
Pragma: no-cache |
6 |
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
Обратите внимание на строку запроса, за которой идет серия заголовков запроса. Заголовок Host является обязательным для клиентов, работающих по HTTP/1.1. Запросы, выполняемые по методу GET, не имеют тела объекта, а запросы, выполняемые по методу POST, могут содержать данные в теле для создания ресурса.
Заголовки запроса играют роль модификаторов сообщения запроса. Полный список имеющихся заголовков запроса не слишком длинный и приведен ниже. Не входящие в перечень заголовки рассматриваются как поля заголовка объекта.
1 |
|
2 |
request-header = Accept |
3 |
| Accept-Charset |
4 |
| Accept-Encoding |
5 |
| Accept-Language |
6 |
| Authorization |
7 |
| Expect |
8 |
| From |
9 |
| Host |
10 |
| If-Match |
11 |
| If-Modified-Since |
12 |
| If-None-Match |
13 |
| If-Range |
14 |
| If-Unmodified-Since |
15 |
| Max-Forwards |
16 |
| Proxy-Authorization |
17 |
| Range |
18 |
| Referer |
19 |
| TE |
20 |
| User-Agent |
В заголовках с префиксом Accept
указываются допустимые для приема клиентом формы информации, язык и набор символов. В From
, Host
, Referer
и User-Agent
указываются детали о клиенте, отправившем запрос. Заголовки с префиксом If-
используются для придания запросу гибкости, и сервер присылает ответ только тогда, когда заданное условие выполняется. В ином случае присылается ответ 304 Not Modified.
Условие может быть задано на основе временной метки или ETag.
Формат сообщений ответа
Формат сообщений ответа сходен с таковым сообщений запроса, за исключением стартовой строки и заголовков. Стартовая строка имеет следующую структуру:
1 |
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF |
- На месте HTTP-Version указывается
HTTP/1.1.
- Status-Code – один из ранее рассматриваемых кодов состояния.
- Reason-Phrase – понятная человеку версия (* поясняющая фраза) кода состояния.
Типичная стартовая строка ответа об успешном выполнении запроса может выглядеть следующим образом:
1 |
HTTP/1.1 200 OK |
Число заголовков ответа также довольно ограничено; полный набор представлен ниже:
1 |
response-header = Accept-Ranges |
2 |
| Age |
3 |
| ETag |
4 |
| Location |
5 |
| Proxy-Authenticate |
6 |
| Retry-After |
7 |
| Server |
8 |
| Vary |
9 |
| WWW-Authenticate |
- В
Age
указывается время в секундах, когда сообщение было сгенерировано на сервере. - Значение
ETag
– хэш-значение объекта, полученное с помощью алгоритма шифрования MD5 (* Message Digest 5); используется для проверки наличия изменений ресурса. - Location используется для инструктирования клиента о перенаправлении и содержит новый URL-адрес.
- В
Server
указывается сервер, который прислал сообщение.
Мы ознакомились с большим объемом теории на данный момент, так что не удивительно, если вы немного задремали. В следующих разделах у нас будет больше практики и мы поработаем с некоторыми инструментами, фреймворками и библиотеками.
Инструменты для просмотра сетевого трафика по HTTP (* поток данных в передающей среде; состоит из передаваемых данных и служебной информации, необходимой для организации их прохождения)
Разработчикам доступно множество инструментов для мониторинга HTTP трафика. Здесь будут перечислены наиболее популярные.
Без сомнений, фаворитом среди веб-разработчиков является инспектор Chrome/Webkit.



Также в их распоряжении имеются прокси для отладки веб-приложений, например, Fiddler (* работает с трафиком между вашим компьютером и удаленным сервером и позволяет просматривать и менять его) для Windows и Charles Proxy для OSX. Мой коллега, Rey Bango, написал замечательную статью на эту тему. Мой коллега, Rey Bango, написал замечательную статью на эту тему.






Из набора программ с интерфейсом командной строки для мониторинга трафика HTTP у нас имеются такие утилиты, как curl, tcpdump и tshark.
Использование HTTP во фреймворках и библиотеках
Теперь, когда мы рассмотрели сообщения запроса/ответа, пришло время ознакомиться с тем, какой API библиотеки и фремворки предоставляют для работы с ними. Мы рассмотрим примеры из ExpressJS (для Node), Ruby on Rails (* фреймворк, написанный на языке программирования Ruby, реализует архитектурный шаблон Model-View-Controller для веб-приложений, а также обеспечивает их интеграцию с веб-сервером и сервером баз данных) и jQuery Ajax. Мы рассмотрим примеры из ExpressJS (для Node), Ruby on Rails (* фреймворк, написанный на языке программирования Ruby, реализует архитектурный шаблон Model-View-Controller для веб-приложений, а также обеспечивает их интеграцию с веб-сервером и сервером баз данных) и jQuery Ajax.
ExpressJS
Если вы создаете веб-серверы на Node.js, то наверняка уже знакомы с ExpressJS. Прототипом ExpressJS послужил веб-фреймворк для Ruby – Sinatra. Не удивительно, что API ExpressJS подобен его API.
Поскольку мы имеем дело с фреймворком для серверной стороны, то при работе с сообщениями HTTP необходимо выполнить два действия:
- Прочитать фрагменты URL и заголовки запроса.
- Добавить заголовки ответа и тело.
Понимание HTTP очень важно для реализации простого добротного RESTful (* веб-службы, построенные с учётом REST (передача состояния представления; архитектурный стиль взаимодействия компонентов распределенного приложения в сети)) - интерфейса между двумя оконечными узлами локальной сети.
ExpressJS как раз предоставляет для этого простой API. Мы не будем рассматривать детали API. Вместо этого я предоставлю вам ссылки на детальную документацию по ExpressJS. Здесь будут перечислены наиболее популярные. Некоторые примеры методов API, связанных с обработкой запросов, приведены ниже:
- req.body: для получения тела запроса.
- req.query: для получения фрагмента запроса URL.
- req.originalUrl
- req.host: для прочтения поля
Host
заголовка. - req.accepts: для получения допустимых на стороне клиента типов MIME (* многоцелевые расширения почты (почтовой службы) в Интернете; набор стандартов для передачи мультимедийной информации посредством электронной почты).
- req.get или req.header: для прочтения любого поля заголовка, переданного в виде аргумента.
Для формирования ответа клиенту ExpressJS предоставляет следующий API:
- res.status: для явного указания кода состояния.
- res.set: для указания определенного заголовка.
- res.send: для отправления HTML, JSON или последовательности октетов.
- res.sendFile: для передачи файла клиенту.
- res.render: для выполнения шаблона представления Express.
- res.redirect: для перенаправления на другой маршрут. Express автоматически добавляет код по умолчанию о перенаправлении 302.
Ruby on Rails
Формат сообщений запроса и ответа сходен (различия есть в стартовой строке и заголовках сообщений).
В Rails модули ActionController и ActionDispatch предоставляют API для обработки сообщений запроса и ответа.
ActionController предоставляет высокоуровневый API для получения URL запроса, обработки результата и перенаправления на другой маршрут. Конечная точка (маршрут) используется для выполнения указанного в нем метода (действия) (* например, если пользователь переходит по /clients/new в вашем приложении для добавления нового клиента, Rails создаст образец ClientsController и вызовет его метод new). Большинство необходимой контекстной (* связанной с конкретным запросом) информации внутри метода становится доступной благодаря объектам request
, response
и params
.
- params: предоставляет доступ к параметрам URL и данным, переданным по методу POST.
- request: содержит информацию о клиенте, заголовках и URL.
- response: используется для установления значений заголовков и кодов состояния.
- render: для исполнения шаблонов.
- redirect_to: используется для перенаправления к другому методу или на другой URL.
ActionDispatch предоставляет тонко гранулированный доступ к сообщениям запроса/ответа при помощи классов ActionDispatch::Request
и ActionDispatch::Response.
Этот модуль предоставляет набор методов для проверки типа запроса (get?(),
post?()
, head?()
, local?()
). Заголовки запроса можно напрямую получить при помощи метода request.headers()
.
Для работы с ответом модуль предоставляет методы cookies(),
location=()
и status=().
Если вы хотите поэкспериментировать, то можете также задать тело ответа вручную при помощи body=().
AJAX (* Asynchronous JavaScript And XML – асинхронный JavaScript + XML) jQuery
Поскольку jQuery – прежде всего, библиотека для клиентской части приложения, то API AJAX предоставляет возможности, противоположные тем, что реализуются на стороне сервера. Другими словами, благодаря ей вы можете прочитывать и изменять сообщения запроса. jQuery предоставляет доступ к простому API при помощи jQuery.ajax(settings):
Передавая объект settings
, в состав которого входит функция обратного вызова beforeSend
, мы можем изменять заголовки запроса. В нее передается объект jqXHR (jQuery XMLHttpRequest), у которого имеется метод (setRequestHeader()
) для указания значений заголовков.
1 |
|
2 |
$.ajax({ |
3 |
url: 'http://www.articles.com/latest', |
4 |
type: 'GET', |
5 |
beforeSend: function (jqXHR) { |
6 |
jqXHR.setRequestHeader('Accepts-Language', 'en-US,en'); |
7 |
}
|
8 |
});
|
- Объект jqXHR также может быть использован для прочтения заголовков ответа при помощи метода
jqXHR.getResponseHeader().
- Если вы хотите выполнять определенные действия по приходу различных кодов состояния, то вы можете указать функцию обратного вызова в объекте
statusCode
.
1 |
|
2 |
$.ajax({ |
3 |
statusCode: { |
4 |
404: function() { |
5 |
alert("page not found"); |
6 |
}
|
7 |
}
|
8 |
});
|
Резюме
Давайте теперь подведем итог нашему краткому разбору протокола HTTP.
Мы ознакомились со структурой URL-адреса, методами и кодами состояния – тремя китами коммуникации при помощи HTTP.
Формат сообщений запроса и ответа сходен (различия есть в стартовой строке и заголовках сообщений). И, наконец, мы рассмотрели, как вы можете работать с заголовками запроса и ответа во фреймворках и библиотеках.
Понимание HTTP очень важно для реализации простого добротного RESTful (* веб-службы, построенные с учётом REST (передача состояния представления; архитектурный стиль взаимодействия компонентов распределенного приложения в сети)) интерфейса между двумя оконечными узлами локальной сети (* ЛС). По большому счету (* исходя из самых строгих требований) эти знания вам также пригодятся при создании вашей сетевой инфраструктуры (* совокупность аппаратных и программных средств, предоставляющая пользователю необходимые сетевые возможности) и обеспечении для конечных пользователей удобства использования.
Во второй части мы разберем реализацию соединений, аутентификацию и кэширование! Тогда и увидимся.