Post - Каким методом передается http-запрос в форме и без формы? Parameters запросе: Как параметры отправляются в HTTP-запрос POST? Отправка http запросов.

Начиная со второй версии 8 платформы, у пользователей и разработчиков появилась возможность использования непосредственно в 1С http запрос. При этом программа поддерживает два типа запросов:

  • POST запросы;
  • GET запросы.

Таким образом, был создан достаточно удобный инструмент для обмена данными и взаимодействия с веб сервисами и службами, работающими через http.

GET запрос

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

  1. Получим тело главной страницы нашего сайта;
  2. Отработаем перенаправление запроса;
  3. Заберем картинку с сайта.

Получение тела сайта

Начнем с простого. На Рис..

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

Рис.2

В первой строке кода мы создаем объект соединения с http ресурсом. Объект может содержать следующие свойства:

  • Сервер — строка подключения, содержащая адрес сервера;
  • Порт – содержит число, указывающее на порт сервера, по умолчанию, в зависимости от типа подключения, можно указать 80 для незащищенных соединений или 443 для защищенных SSL.
  • Имя пользователя – указывается, если необходима авторизация на сервере;
  • Пароль – пароль пользователя на указанном ресурсе;
  • Прокси – может содержать объект типа ИнтернетПрокси, указывается, когда для связи с сервером используется прокси;
  • ЗащищенноеСоединение – по умолчанию имеет значение ЛОЖЬ, переключение в ИСТИНА указывает на использование https протокола.

Кроме этого, у объекта HTTPСоединение существуют свои методы, обращение к которым позволяет более полно описать алгоритм выполнения обработчика:

  • ВызватьHTTPметод – содержит два обязательных параметра HTTPметод и HTTPзапрос, поддерживает возможность записи тела ответа в файл, указанный в третьем параметре;
  • Записать – с помощью PUT запроса отправляет данные на сервер;
  • Изменить – изменяет объект, обрабатывая PATCH запросы;
  • ОтправитьДляОбработки – метод указывающий на использование POST запроса, как и во всех предыдущих методах, обязательно должен содержать текст запроса, так же может передавать адрес файла ответа для записи данных;
  • Получить – о нем подробнее будет рассказано ниже;
  • ПолучитьЗаголовки – еще один метод, который будет использован в статье;
  • Удалить – фактически это запрос Delite, который удаляет переданный в запросе ресурс с сервера.

Второй строкой мы создаем запрос к выбранному сайту, текст нашего обращения содержит один слэш, а это значит, что мы хотим получить главную страницу. Если бы следом за слешем шло какое-либо выражение, например «page2» или «news» мы бы получили другую страницу.

Третья строка выполняет наш запрос к серверу.

В четвертой мы показываем результат.

Отработка перенаправления http запроса

Представим ситуацию, когда нам надо программно получить результат поиска через любую поисковую систему по ключу «Запросы в 1с». Участок кода, необходимый для обращения к GOOGLE указан на рис.3

Рис.3

Здесь помимо уже знакомых нам конструкций присутствуют Заголовки и КодСостояния. Разберемся с ними.

КодСостояния – стандартная величина, оговоренная в «Request for Comments» , может принимать следующие значения:

  1. Если все нормально вернется значение в диапазоне от 100 до 299;
  2. В случае перенаправления вернется код в диапазоне от 300 до 399, в нашем случае удачное постоянное перенаправление на ресурс определится кодом 301;
  3. При ошибках в запросе параметр примет значение от 400 до 499;
  4. Значение в области 500-599 указывает на проблемы с сервером.

У каждой страницы есть заголовок, в тексте которого можно выделить несколько параметров (Рис.4):

  1. Схему подключения (все, что идет до двух слешей «//»);
  2. Адресную строку соединения;
  3. Имя пользователя и пароль;
  4. Порт и хост для подключения.

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

Рис.5

Здесь нет новых функций и способов работы с запросами, мы фактически создаем текстовый документ из тела сайта и запускаем страницу в браузере.

Файл мы помещаем в корень диска D и называем test.

Забираем картинку с сайта

Возникает естественный вопрос: если нам не нужен весь сайт целиком, а необходимо получить только отдельные его элементы, можно ли это сделать и как? Да можно. Код программы, позволяющий это сделать, представлен на Рис.6

Рис.6

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

Мы использовали браузер Opera для доступа к сайту. В нем имеется один важный для нас инструмент, при щелчке правой кнопкой мыши на элементе, можно вызвать контекстное меню, один из пунктов которого «Посмотреть код элемента».

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

POST-запрос

В отличие от несложных Get запросов, POST http запросы имеют текстовое тело, которое может храниться как в обычном текстовом виде, так и в виде файлов с расширением xml, soap, json. В сети достаточно много инструментов для создания текстов запроса, которые позволяют отлаживать и мониторить исполнение тех или иных обращений.

В 1С для того, чтобы запустить запрос с определенным текстом, у объекта HTTPзапрос есть процедура УстановитьТелоИзСтроки.

  1. Да, но не штатными средствами браузера. Только если с помощью инструментов разработчика или другим HTTP-клиентом, коих великое множество во главе с curl . И уж точно не стоит ожидать, что ответ будет таким же, т. к. разные "методы" предполагают совершение с запрашиваемым ресурсом разных действий (обычно GET это чтение, а POST это добавление нового).
  2. Не совсем. Формально да, но поля, передаваемые в строке запроса, не могут в такой ситуации быть привязаны к полям формы, т. е. не могут быть изменены при пользовательском взаимодействии с веб-страницей (инструменты разработчика, конечно, могут всё). Что в action -атрибуте формы указано, то в строке запроса и уйдёт.
  3. Из п. 3 следует, что это должна быть форма без полей. Даже у кнопки отправки формы должен отсутствовать атрибут name , иначе она тоже будет считаться полем формы и её значение будет отправлено в теле запроса.
  4. Существуют, но не в типичных браузерах, разумеется. telnet , к примеру. Установите telnet -клиент и выполните в командной строке: telnet mail.ru 80 (да, важно явно указать порт). Он подключится к серверу. Наберите приведённое вами тело как есть (у меня в PowerShell ввод почему-то не уходил эхом в стандартный вывод, но он воспринимался) и дважды переведите строку для завершения запроса. В стандартный вывод будет выведен ответ.
    Для HTTPS же потребуется что-нибудь посерьёзнее.

    Спускаться на настолько низкий уровень (telnet ничего не знает об HTTP) нужно только для очень узкого круга задач. Чтобы отправить сколько-нибудь нетривиальный запрос, надо погрузиться в дебри HTTP и преобразовать ваши данные в правильный для него формат. Поэтому для совершения произвольных HTTP-запросов чаще пользуются специализированными HTTP-клиентами. Например, вышеупомянутым curl . У многих скриптовых языков (Python, Ruby) также имеются HTTP-клиенты в стандартной библиотеке, оперирующие типами данных языка и занимающиеся преобразованием в нужные форматы самостоятельно.

  5. Но зачем? Нет. Разметка страницы — результат не более чем одного запроса. Нет, фреймы открывают отдельные страницы, которые частью исходной не являются. Нет, загрузка с помощью JavaScript куска страницы не сделает этот кусок частью исходной; к тому же, JavaScript может быть выключен или не поддерживаться.

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

Но на HTML, формах и ссылках мир HTTP не ограничивается. Особенно сейчас, когда веб кишит разнообразными HTTP API и SPA на их основе. Современные браузеры не так просты: с помощью JavaScript они могут связывать практически любой ввод от пользователя с практически любым HTTP-запросом, нужно это лишь реализовать с помощью браузерного скрипта (кроме JavaScript на данный момент нет выбора).

Кроме того, нынче на просторах серверов, бывает, пасутся стада микросервисов, общающиеся (между собой и иногда даже между стадами) на языке HTTP словами на JSON/XML/и т. д. Там браузер не фигурирует ни на одной из сторон.

запроса структура (8)

В запросе HTTP GET параметры отправляются как строка запроса :

Http://example.com/page?parameter=value&also=another

В запросе HTTP POST параметры не отправляются вместе с URI.

Где значения? В заголовке запроса? В теле запроса? На что это похоже?

Answers

Значения форм в HTTP-POST-сообщениях отправляются в тело запроса в том же формате, что и запрос.

Для получения дополнительной информации см. spec .

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

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

POST /?AuthId=YOURKEY&Action=WebServiceAction&Signature=rcLXfkPldrYm04 HTTP/1.1 Content-Type: text/tab-separated-values; charset=iso-8859-1 Content-Length: Host: webservices.domain.com Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: identity User-Agent: Mozilla/3.0 (compatible; Indy Library) name id John G12N Sarah J87M Bob N33Y

Этот подход логически объединяет QueryString и Body-Post с использованием одного Content-Type который является «инструкцией по синтаксическому разбору» для веб-сервера.

Обратите внимание: HTTP / 1.1 завернута в #32 (пробел) слева и с #10 (Line feed) справа.

Прежде всего, давайте GET и POST

Получить: Это HTTP запрос по умолчанию, который делается на сервере, и используется для извлечения данных с сервера и строки запроса, которая появляется после? в URI используется для извлечения уникального ресурса.

это формат

GET /someweb.asp?data=value HTTP/1.0

здесь data=value - переданное значение строки запроса.

POST: он используется для безопасного отправления данных на сервер, чтобы все, что необходимо, это формат запроса POST

POST /somweb.aspHTTP/1.0 Host: localhost Content-Type: application/x-www-form-urlencoded //you can put any format here Content-Length: 11 //it depends Name= somename

Почему POST над GET?

В GET значение, отправляемое на серверы, обычно добавляется к базовому URL-адресу в строке запроса. Это позволяет взломать ваши данные (это было проблемой в дни для Facebook, где были установлены ваши учетные данные), поэтому POST используемый для отправки данных на сервер, который использовал Request Body для отправки ваших данных на сервер, который более безопасен, поскольку он скрывает ваши данные, и он получает ваши данные из полей, вычисляет их длину и добавляет их в header для content-length и никакие важные данные напрямую не добавляются к URL

теперь, когда ваш запрос защищен, любые значения, отправляемые на сервер, могут быть отправлены в Request Body поскольку имя подразумевает, что оно будет содержать пользователей данных, которые хотели бы отправить (и Он отправляется в URL Encoded формате URL Encoded), а Request Headers будут сохраняйте запрос безопасным путем сравнения значений в Request Body с Request Headers

Вы можете использовать сетевой раздел Google Developer Tools, чтобы узнать основную информацию о том, как запросы выполняются на серверах.

и вы всегда можете добавить больше значений в Request Headers такие как Cache-Control , Origin , Accept .

Короткий ответ: в POST-запросах значения отправляются в «тело» запроса. В веб-формах они, скорее всего, отправляются с медиа-типом application/x-www-form-urlencoded или multipart/form-data . Языки программирования или фреймворки, предназначенные для обработки веб-запросов, обычно выполняют «The Right Thing ™» с такими запросами и обеспечивают вам легкий доступ к легко декодированным значениям (например, $_REQUEST или $_POST в PHP или cgi.FieldStorage() , flask.request.form в Python).

Теперь давайте немного отвлечемся, что может помочь понять разницу;)

Разница между запросами GET и POST в значительной степени семантична. Они также «используются» по-разному, что объясняет разницу в том, как передаются значения.

GET (соответствующий раздел RFC)

При выполнении запроса GET вы запрашиваете сервер для одного или набор объектов. Чтобы клиент мог фильтровать результат, он может использовать так называемую «строку запроса» URL-адреса. Строка запроса является частью после? , Это часть синтаксиса URI .

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

Обратите внимание, что ключи и значения являются частью URI. Браузеры могут налагать ограничение на длину URI. В стандарте HTTP указано, что ограничений нет. Но на момент написания этой статьи большинство браузеров ограничивают URI (у меня нет конкретных значений). Запросы GET никогда не должны использоваться для отправки новой информации на сервер. Особенно не крупные документы. Здесь вы должны использовать POST или PUT .

POST (соответствующий раздел RFC)

При выполнении запроса POST клиент фактически отправляет новый документ удаленному хосту. Таким образом, строка запроса не (семантически) имеет смысл. Вот почему у вас нет доступа к ним в вашем коде приложения.

POST немного сложнее (и более гибким):

При получении запроса POST вы всегда должны ожидать «полезную нагрузку», или в терминах HTTP: тело сообщения . Тело сообщения само по себе довольно бесполезно, поскольку нет стандартного (насколько я могу судить. Может быть, application / octet-stream?) Формата. Формат тела определяется заголовком Content-Type . При использовании элемента HTML FORM с method="POST" это обычно application/x-www-form-urlencoded . Другим очень распространенным типом является multipart/form-data если вы используете загрузку файлов. Но может быть что угодно : от text/plain , над application/json или даже с настраиваемым application/octet-stream .

В любом случае, если запрос POST выполняется с Content-Type который не может быть обработан приложением, он должен вернуть код состояния 415 .

Большинство языков программирования (и / или веб-фреймворки) предлагают способ де-кодирования тела сообщения от / до наиболее распространенных типов (например, application/x-www-form-urlencoded , multipart/form-data или application/json) , Так что это легко. Пользовательские типы требуют потенциально немного больше работы.

Используя пример стандартного HTML-кодированного документа, приложение должно выполнить следующие шаги:

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

Опять же, такие языки, как PHP, или веб-фреймворки для других популярных языков, вероятно, справятся с этим для вас. Исключением является ошибка 415 . Никакая структура не может предсказать, какие типы контента ваше приложение выбирает для поддержки и / или не поддержки. Это зависит от вас.

PUT (соответствующий раздел RFC)

Запрос PUT обрабатывается точно так же, как запрос POST . Большая разница заключается в том, что запрос POST должен позволить серверу решить, как (и если вообще) создать новый ресурс. Исторически (из теперь устаревшего RFC2616 он должен был создать новый ресурс как «подчиненный» (дочерний) URI, куда был отправлен запрос).

Предполагается, что запрос PUT должен «откладывать» ресурс именно в этом URI и именно с этим контентом. Не больше, не меньше. Идея заключается в том, что клиент несет ответственность за создание полного ресурса до «PUTting». Сервер должен принять его как есть на данном URL-адресе.

Как следствие, запрос POST обычно не используется для замены существующего ресурса. Запрос PUT может создавать и заменять.

Примечание

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

Помимо точечных сегментов в иерархических путях, сегмент пути считается непрозрачным по обобщенному синтаксису. В URI, создающих приложения, часто используются зарезервированные символы, разрешенные в сегменте, для разграничения подкомпонентов, специфичных для конкретной схемы или разнесения. Например, зарезервированные символы с запятой (";") и равно ("=") часто используются для разграничения параметров и значений параметров, применимых к этому сегменту. Зарезервированный символ запятой (",") часто используется для аналогичных целей. Например, один производитель URI может использовать сегмент, такой как «name; v = 1.1», чтобы указать ссылку на версию 1.1 «name», тогда как другой может использовать сегмент, такой как «name, 1.1», чтобы указать его. Типы параметров могут быть определены с помощью специфичной для схемы семантики, но в большинстве случаев синтаксис параметра специфичен для реализации алгоритма разыменования URI.

Вы не можете вводить его непосредственно в строке URL браузера.

Вы можете увидеть, как данные POST отправляются в Интернете с помощью HTTP-заголовков, например. Результат будет примерно таким

Http://127.0.0.1/pass.php POST /pass.php HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate DNT: 1 Referer: http://127.0.0.1/pass.php Cookie: passx=87e8af376bc9d9bfec2c7c0193e6af70; PHPSESSID=l9hk7mfh0ppqecg8gialak6gt5 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 30 username=zurfyx&pass=password

Где он говорит

Content-Length: 30 username=zurfyx&pass=password

будут значения post.

Значения отправляются в тело запроса в том формате, который указан в типе содержимого.

Обычно тип содержимого - application/x-www-form-urlencoded , поэтому тело запроса использует тот же формат, что и строка запроса:

Parameter=value&also=another

Когда вы используете загрузку файла в форме, вместо этого вы используете кодировку multipart/form-data , которая имеет другой формат. Это сложнее, но вам обычно не нужно заботиться о том, как это выглядит, поэтому я не буду показывать пример, но может быть полезно знать, что он существует.

Тип носителя по умолчанию в POST-запросе - application/x-www-form-urlencoded . Это формат для кодирования пар ключ-значение. Ключи могут быть дублированы. Каждая пара ключ-значение разделяется символом & , и каждый ключ отделяется от его значения символом = .

Например:

Name: John Smith Grade: 19

Записывается как:

Name=John+Smith&Grade=19

Он помещается в тело запроса после заголовков HTTP.

Вопрос перечитывает. Фактический заданный вопрос не похож на префиксы поставщиков в свойствах CSS, где целесообразно проверять будущее и думать о поддержке поставщиков и официальных стандартах. Фактический заданный вопрос более сродни выбору имен параметров запроса URL. Никто не должен заботиться о том, кто они. Но совпадение имен с обычными - это совершенно правильная, и общая, и правильная вещь.

Обоснование:
Речь идет о соглашениях между разработчиками для пользовательских заголовков конкретных приложений - « данных, имеющих отношение к их учетной записи » - которые не имеют ничего общего с поставщиками, органами стандартов или протоколами, которые должны быть реализованы третьими сторонами, за исключением того, что разработчик, о котором идет речь просто нужно избегать заголовков, которые могут иметь другое предназначение для использования серверами, прокси или клиентами. По этой причине приведенные примеры «X-Gzip / Gzip» и «X-Forwarded-For / Forwarded-For» являются спорными. Возникает вопрос о соглашениях в контексте частного API, аналогичных соглашениям об именах параметров URL-запроса. Это вопрос предпочтения и расстояния между именами; опасения по поводу «X-ClientDataFoo», поддерживаемые любым прокси-сервером или поставщиком без «X», явно неуместны.

В префиксе «X-» нет ничего особенного или волшебного, но это помогает понять, что это настраиваемый заголовок. На самом деле, RFC-6648 и др. Помогают предотвратить использование префикса «X-», поскольку - поскольку поставщики HTTP-клиентов и серверов отказываются от префикса - ваши приложения, частные API-интерфейсы, персональные данные, механизм передачи становится еще лучше изолированным от коллизий между именами и небольшим количеством официальных зарезервированных заголовков. Тем не менее, мои личные предпочтения и рекомендации - сделать еще один шаг и сделать, например, «X-ACME-ClientDataFoo» (если ваша компания-виджет «ACME»).

IMHO спецификация IETF недостаточно специфична для ответа на вопрос OP, поскольку он не может отличить совершенно разные варианты использования: (A) поставщики, внедряющие новые глобально применимые функции, такие как «Forwarded-For», с одной стороны, vs. (B) разработчики приложений передают строки, зависящие от приложения, к клиенту и серверу. Спектр касается только первого, (A). Вопрос здесь в том, существуют ли соглашения для (B). Есть. Они включают группирование параметров в алфавитном порядке и разделение их от многих соответствующих стандартам заголовков типа (A). Использование префикса «X-» или «X-ACME-» является удобным и законным для (B) и не противоречит (A). Чем больше продавцов перестанут использовать «X-» для (A), тем станут более четкими (B).

Пример:
Google (которые несут немного веса в различных органах стандартизации) - на сегодняшний день, 20141102 в этом незначительном изменении моего ответа - в настоящее время используется «X-Mod-Pagespeed», чтобы указать версию своего модуля Apache, участвующего в преобразуя данный ответ. Кто-нибудь действительно предлагает, чтобы Google использовал «Mod-Pagespeed» без «X-» и / или попросил IETF благословить его использование?

Резюме:
Если вы используете пользовательские заголовки HTTP (как иногда подходящую альтернативу куки-файлам) в своем приложении для передачи данных на ваш сервер, и эти заголовки явно не предназначены для использования вне контекста вашего приложения, сопоставление имен с префиксом «X-» или «X-FOO-» является разумным и общепринятым.

Являетесь вы программистом или нет, вы видели его повсюду в Интернете. На данный момент в адресной строке браузера отображается нечто, что начинается с «http: //». Даже ваш первый скрипт Hello World отправил HTTP-header без вашего понимания. В этой статье мы собираемся узнать об основах HTTP-заголовков и о том, как их можно использовать в наших веб-приложениях.

Что такое HTTP Headers?

HTTP значит "Hypertext Transfer Protocol" (Протокол передачи гипертекста). Всемирная паутина использует этот протокол. Он был создан в начале 1990-х годов. Почти всё, что вы видите в вашем браузере, передаётся на ваш компьютер через HTTP. Например, когда вы открыли страницу этой статьи, ваш браузер отправил более 40 HTTP-запросов и получил HTTP-ответы для каждого из них.

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

Пример

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

GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1 Host: net.tutsplus.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120 Pragma: no-cache Cache-Control: no-cache

Первая строка - это "Request Line", которая содержит некоторую базовую информацию по запросу. Остальные - HTTP заголовки.

После этого запроса ваш браузер получает ответ HTTP, который может выглядеть так:

HTTP/1.x 200 OK Transfer-Encoding: chunked Date: Sat, 28 Nov 2009 04:36:25 GMT Server: LiteSpeed Connection: close X-Powered-By: W3 Total Cache/0.8 Pragma: public Expires: Sat, 28 Nov 2009 05:36:25 GMT Etag: "pub1259380237;gz" Cache-Control: max-age=3600, public Content-Type: text/html; charset=UTF-8 Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT X-Pingback: http://net.tutsplus.com/xmlrpc.php Content-Encoding: gzip Vary: Accept-Encoding, Cookie, User-Agent Top 20+ MySQL Best Practices - Nettuts+

Первая строка - это «Строка состояния», за которой следуют «HTTP-заголовки», до пустой строки. После этого начинается «содержимое» (в данном случае - HTML вывод).

Когда вы смотрите на исходный код веб-страницы в своём браузере, вы видите только часть HTML, а не заголовки HTTP, хотя они фактически были переданы вместе.

Эти HTTP-запросы также отправляются и принимаются для других вещей, таких как изображения, CSS-файлы, файлы JavaScript и т. д. Именно поэтому я сказал ранее, что ваш браузер отправил не менее 40 или более HTTP-запросов, поскольку вы загрузили только эту страницу статьи.

Теперь давайте рассмотрим структуру более подробно.

Как увидеть HTTP Headers

Для анализа HTTP-заголовков я использую следующие расширения Firefox:

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

Теперь мы рассмотрим некоторые из наиболее распространенных HTTP headers , найденных в HTTP requests.

Почти все эти заголовки можно найти в массиве $ _SERVER в PHP. Вы также можете использовать функцию getallheaders() для извлечения всех заголовков одновременно.

Host

HTTP-запрос отправляется на определенные IP-адреса. Но так как большинство серверов способны размещать несколько сайтов под одним IP, они должны знать, какое доменное имя ищет браузер.

Host: net.tutsplus.com

Это в основном имя host, включая домен и поддомен.

В PHP его можно найти, как $_SERVER["HTTP_HOST"] или $_SERVER["SERVER_NAME"].

User-Agent

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)

Этот заголовок может содержать несколько частей информации, таких как:

Именно так веб-сайты могут собирать определённую общую информацию о своих системах surfers. Например, они могут определить, использует ли surfer мобильный браузер и перенаправляет их на мобильную версию своего веб-сайта, который лучше работает с низким разрешением.

В PHP может быть выражен так: $_SERVER["HTTP_USER_AGENT"].

If (strstr($_SERVER["HTTP_USER_AGENT"],"MSIE 6")) { echo "Please stop using IE6!"; }

Accept-Language

Accept-Language: en-us,en;q=0.5

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

В PHP его можно найти так: $ _SERVER ["HTTP_ACCEPT_LANGUAGE"].

If (substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2) == "fr") { header("Location: http://french.mydomain.com"); }

Accept-Encoding

Accept-Encoding: gzip,deflate

Большинство современных браузеров поддерживают gzip и отправляют это в header. Затем веб-сервер может отправить выходной HTML-код в сжатом формате. Это позволяет уменьшить размер до 80% для экономии пропускной способности и времени.

В PHP его можно найти так: $ _SERVER ["HTTP_ACCEPT_ENCODING"]. Однако, когда вы используете функцию обратного вызова ob_gzhandler() , она будет проверять значение автоматически, поэтому вам это не нужно.

// enables output buffering // and all output is compressed if the browser supports it ob_start("ob_gzhandler");

If-Modified-Since

Если веб-документ уже сохранен в кеше в браузере и вы посещаете его снова, ваш браузер может проверить, был ли документ обновлён, отправив следующее:

Если он не изменялся с этой даты, сервер отправляет код ответа «304 Not Modified», а содержимое - нет, и браузер загружает содержимое из cache.

В PHP его можно найти так: $ _SERVER ["HTTP_IF_MODIFIED_SINCE"].

// assume $last_modify_time was the last the output was updated // did the browser send If-Modified-Since header? if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { // if the browser cache matches the modify time if ($last_modify_time == strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { // send a 304 header, and no content header("HTTP/1.1 304 Not Modified"); exit; } }

Существует также HTTP-заголовок Etag, который можно использовать для проверки текущего кэша. Мы поговорим об этом в ближайшее время.

Cookie

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

Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120; foo=bar

Это пары name=value, разделённые точками с запятой. Cookies могут также содержать id сеанса.

В PHP отдельные cookie-файлы могут быть доступны с помощью массива $ _COOKIE. Вы можете напрямую обращаться к переменным сеанса, используя массив $ _SESSION, и если вам нужен id сеанса, вы можете использовать функцию session_id () вместо cookie.

Echo $_COOKIE["foo"]; // output: bar echo $_COOKIE["PHPSESSID"]; // output: r2t5uvjq435r4q7ib3vtdjq120 session_start(); echo session_id(); // output: r2t5uvjq435r4q7ib3vtdjq120

Referer

Как следует из названия, этот HTTP header содержит ссылочный url.

Например, если я зашел на домашнюю страницу Nettuts + и нажал ссылку на статью, этот header будет отправлен в мой браузер:

Referer: http://net.tutsplus.com/

В PHP его можно найти как $ _SERVER ["HTTP_REFERER"].

If (isset($_SERVER["HTTP_REFERER"])) { $url_info = parse_url($_SERVER["HTTP_REFERER"]); // is the surfer coming from Google? if ($url_info["host"] == "www.google.com") { parse_str($url_info["query"], $vars); echo "You searched on Google for this keyword: ". $vars["q"]; } } // if the referring url was: // http://www.google.com/search?source=ig&hl=en&rlz=&=&q=http+headers&aq=f&oq=&aqi=g-p1g9 // the output will be: // You searched on Google for this keyword: http headers

Возможно, вы заметили, что слово «referrer» написано с ошибкой, как «referer». К сожалению, он превратился в официальную спецификацию HTTP подобным образом и застрял.

Authorization

Authorization: Basic bXl1c2VyOm15cGFzcw==

Данные внутри header имеют кодировку base64. Например, base64_decode ("bXl1c2VyOm15cGFzcw ==") возвратит "myuser: mypass"

В PHP эти значения можно найти как $ _SERVER ["PHP_AUTH_USER"] и $ _SERVER ["PHP_AUTH_PW"].

Подробнее об этом будет, когда мы поговорим о заголовке WWW-Authenticate.

Заголовки HTTP в ответах HTTP

Теперь мы рассмотрим некоторые из наиболее распространенных HTTP headers, найденных в HTTP-ответах.

В PHP вы можете установить заголовки ответа, используя функцию header() . PHP уже отправляет определённые заголовки автоматически, для загрузки содержимого и настройки файлов cookie и прочее... Вы можете увидеть headers, которые отправляются или будут отправляться с помощью функции headers_list () . Вы можете проверить, были ли уже отправлены заголовки с помощью функции headers_sent() .

Cache-Control

Определение из w3.org: «Поле заголовка Cache-Control используется для указания директив, которые ДОЛЖНЫ выполняться всеми механизмами кэширования по цепочке запросов/ответов». Эти «механизмы кэширования» включают шлюзы и прокси, которые может использовать ваш интернет-провайдер.

Cache-Control: max-age=3600, public

"public" означает, что ответ может быть кэширован кем угодно. "max-age" указывает, сколько секунд действителен кеш. Разрешение кэширования вашего сайта может снизить нагрузку на сервер и пропускную способность, а также увеличить время загрузки в браузере.

Кэширование также может быть предотвращено с помощью директивы "no-cache".

Cache-Control: no-cache

Content-Type

Этот header указывает "mime-type" документа. Затем браузер определяет, как интерпретировать содержимое на основании этого. Например, страница html (или PHP-скрипт с выходом html) может возвращать это:

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

"text" - это тип, а "html" - подтип документа. Заголовок также может содержать больше информации, такой как charset.

Для gif-изображения это может быть отправлено.

Content-Type: image/gif

Браузер может использовать внешнее приложение или расширение браузера на основе mime-type. Например, это приведет к загрузке Adobe Reader:

Content-Type: application/pdf

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

Вы можете найти список общих типов mime .

В PHP вы можете использовать функцию finfo_file() для определения mime-типа файла.

Content-Disposition

Этот header указывает браузеру открыть окно загрузки файла, вместо того, чтобы пытаться проанализировать содержимое. Пример:

Content-Disposition: attachment; filename="download.zip"

Это заставит браузер сделать это:

Обратите внимание, что соответствующий заголовок Content-Type также должен быть отправлен вместе с этим:

Content-Type: application/zip Content-Disposition: attachment; filename="download.zip"

Content-Length

Когда контент будет передаваться браузеру, сервер может указать его размер (в байтах), используя этот header.

Content-Length: 89123

Это особенно полезно при загрузке файлов. Именно так браузер может определить ход загрузки.

Например, вот сценарий-макет, который я написал, имитирует медленную загрузку.

// it"s a zip file header("Content-Type: application/zip"); // 1 million bytes (about 1megabyte) header("Content-Length: 1000000"); // load a download dialogue, and save it as download.zip header("Content-Disposition: attachment; filename="download.zip""); // 1000 times 1000 bytes of data for ($i = 0; $i < 1000; $i++) { echo str_repeat(".",1000); // sleep to slow down the download usleep(50000); }

Вот результат:

Теперь я собираюсь закомментировать заголовок Content-Length

// it"s a zip file header("Content-Type: application/zip"); // the browser won"t know the size // header("Content-Length: 1000000"); // load a download dialogue, and save it as download.zip header("Content-Disposition: attachment; filename="download.zip""); // 1000 times 1000 bytes of data for ($i = 0; $i < 1000; $i++) { echo str_repeat(".",1000); // sleep to slow down the download usleep(50000); }

Теперь результат такой:

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

Etag

Это еще один header, который используется для кеширования. Это выглядит так:

Etag: "pub1259380237;gz"

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

If-None-Match: "pub1259380237;gz"

Если значение Etag документа совпадает с этим, сервер будет отправлять код 304 вместо 200, и никакого содержимого. Браузер будет загружать содержимое из своего кеша.

Last-Modified

Как следует из названия, этот header указывает дату последнего изменения документа в формате GMT:

Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT $modify_time = filemtime($file); header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modify_time) . " GMT");

Это предлагает браузеру другой способ для cache документа. Браузер может отправить это в HTTP-запросе:

Мы уже говорили об этом ранее в разделе "If-Modified-Since".

Location

Этот заголовок используется для перенаправления. Если код ответа 301 или 302, сервер также должен отправить этот header. Например, когда вы перейдете на страницу http://www.nettuts.com , ваш браузер получит следующее:

HTTP/1.x 301 Moved Permanently ... Location: http://net.tutsplus.com/ ...

В PHP вы можете перенаправить surfer так:

Header("Location: http://net.tutsplus.com/");

По умолчанию, это отправит 302 код ответа. Если вы хотите вместо 301 отправить:

Header("Location: http://net.tutsplus.com/", true, 301);

Set-Cookie

Когда веб-сайт хочет установить или обновить файл cookie в вашем браузере, он будет использовать этот header.

Set-Cookie: skin=noskin; path=/; domain=.amazon.com; expires=Sun, 29-Nov-2009 21:42:28 GMT Set-Cookie: session-id=120-7333518-8165026; path=/; domain=.amazon.com; expires=Sat Feb 27 08:00:00 2010 GMT

Каждый файл cookie отправляется как отдельный header. Обратите внимание, что файлы cookie, установленные с помощью JavaScript, не проходят через HTTP headers.

В PHP вы можете установить cookie-файлы, используя функцию setcookie() , а PHP отправляет соответствующие HTTP headers.

Setcookie("TestCookie", "foobar");

Что приводит к отправке этого заголовка:

Set-Cookie: TestCookie=foobar

Если дата истечения срока действия не указана, cookie удаляется, когда окно браузера закрыто.

WWW-Authenticate

Сайт может отправить этот header для аутентификации пользователя через HTTP. Когда браузер увидит этот header, он откроет диалоговое окно входа в систему.

WWW-Authenticate: Basic realm="Restricted Area"

Что будет выглядеть так:

HTTP - это протокол передачи гипертекста между распределёнными системами. По сути, http является фундаментальным элементом современного Web-а. Как уважающие себя веб разработчики, мы должны знать о нём как можно больше.

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

Также в этой статье я буду, в основном, ссылаться на стандарт RFC 2616 : Hypertext Transfer Protocol -- HTTP/1.1.

Основы HTTP

HTTP обеспечивает общение между множеством хостов и клиентов, а также поддерживает целый ряд сетевых настроек.

В основном, для общения используется TCP/IP, но это не единственный возможный вариант. По умолчанию, TCP/IP использует порт 80, но можно заюзать и другие.

Общение между хостом и клиентом происходит в два этапа: запрос и ответ. Клиент формирует HTTP запрос, в ответ на который сервер даёт ответ (сообщение). Чуть позже, мы более подробно рассмотрим эту схему работы.

Текущая версия протокола HTTP - 1.1, в которой были введены некоторые новые фишки. На мой взгляд, самые важные из них это: поддержка постоянно открытого соединения, новый механизм передачи данных chunked transfer encoding, новые заголовки для кэширования. Что-то из этого мы рассмотрим во второй части данной статьи.

URL

Сердцевиной веб-общения является запрос, который отправляется через Единый указатель ресурсов (URL). Я уверен, что вы уже знаете, что такое URL адрес, однако для полноты картины, решил всё-таки сказать пару слов. Структура URL очень проста и состоит из следующих компонентов:

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

Методы

С помощью URL, мы определяем точное название хоста, с которым хотим общаться, однако какое действие нам нужно совершить, можно сообщить только с помощью HTTP метода. Конечно же существует несколько видов действий, которые мы можем совершить. В HTTP реализованы самые нужные, подходящие под нужды большинства приложений.

Существующие методы:

GET : получить доступ к существующему ресурсу. В URL перечислена вся необходимая информация, чтобы сервер смог найти и вернуть в качестве ответа искомый ресурс.

POST : используется для создания нового ресурса. POST запрос обычно содержит в себе всю нужную информацию для создания нового ресурса.

PUT : обновить текущий ресурс. PUT запрос содержит обновляемые данные.

DELETE : служит для удаления существующего ресурса.

Данные методы самые популярные и чаще всего используются различными инструментами и фрэймворками. В некоторых случаях, PUT и DELETE запросы отправляются посредством отправки POST, в содержании которого указано действие, которое нужно совершить с ресурсом: создать, обновить или удалить.

Также HTTP поддерживает и другие методы:

HEAD : аналогичен GET. Разница в том, что при данном виде запроса не передаётся сообщение. Сервер получает только заголовки. Используется, к примеру, для того чтобы определить, был ли изменён ресурс.

TRACE : во время передачи запрос проходит через множество точек доступа и прокси серверов, каждый из которых вносит свою информацию: IP, DNS. С помощью данного метода, можно увидеть всю промежуточную информацию.

OPTIONS : используется для определения возможностей сервера, его параметров и конфигурации для конкретного ресурса.

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

В ответ на запрос от клиента, сервер отправляет ответ, который содержит, в том числе, и код состояния. Данный код несёт в себе особый смысл для того, чтобы клиент мог отчётливей понять, как интерпретировать ответ:

1xx: Информационные сообщения

Набор этих кодов был введён в HTTP/1.1. Сервер может отправить запрос вида: Expect: 100-continue, что означает, что клиент ещё отправляет оставшуюся часть запроса. Клиенты, работающие с HTTP/1.0 игнорируют данные заголовки.

2xx: Сообщения об успехе

Если клиент получил код из серии 2xx, то запрос ушёл успешно. Самый распространённый вариант - это 200 OK. При GET запросе, сервер отправляет ответ в теле сообщения. Также существуют и другие возможные ответы:

  • 202 Accepted : запрос принят, но может не содержать ресурс в ответе. Это полезно для асинхронных запросов на стороне сервера. Сервер определяет, отправить ресурс или нет.
  • 204 No Content : в теле ответа нет сообщения.
  • 205 Reset Content : указание серверу о сбросе представления документа.
  • 206 Partial Content : ответ содержит только часть контента. В дополнительных заголовках определяется общая длина контента и другая инфа.

3xx: Перенаправление

Своеобразное сообщение клиенту о необходимости совершить ещё одно действие. Самый распространённый вариант применения: перенаправить клиент на другой адрес.

  • 301 Moved Permanently : ресурс теперь можно найти по другому URL адресу.
  • 303 See Other : ресурс временно можно найти по другому URL адресу. Заголовок Location содержит временный URL.
  • 304 Not Modified : сервер определяет, что ресурс не был изменён и клиенту нужно задействовать закэшированную версию ответа. Для проверки идентичности информации используется ETag (хэш Сущности - Enttity Tag);

4xx: Клиентские ошибки

Данный класс сообщений используется сервером, если он решил, что запрос был отправлен с ошибкой. Наиболее распространённый код: 404 Not Found. Это означает, что ресурс не найден на сервере. Другие возможные коды:

  • 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 : это может случиться, если на сервере произошла ошибка или он перегружен. Обычно в этом случае, сервер не отвечает, а время, данное на ответ, истекает.

Форматы сообщений запроса/ответа

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

Давайте посмотрим на структуру передаваемого сообщения через HTTP:

Message = *() CRLF [] = Request-Line | Status-Line = Field-Name ":" Field-Value

Между заголовком и телом сообщения должна обязательно присутствовать пустая строка. Заголовков может быть несколько:

Тело ответа может содержать полную информацию или её часть, если активирована соответствующая возможность (Transfer-Encoding: chunked). HTTP/1.1 также поддерживает заголовок Transfer-Encoding.

Общие заголовки

Вот несколько видов заголовков, которые используются как в запросах, так и в ответах:

General-header = Cache-Control | Connection | Date | Pragma | Trailer | Transfer-Encoding | Upgrade | Via | Warning

Что-то мы уже рассмотрели в этой статье, что-то подробней затронем во второй части.

Заголовок via используется в запросе типа TRACE, и обновляется всеми прокси-серверами.

Заголовок Pragma используется для перечисления собственных заголовков. К примеру, Pragma: no-cache - это то же самое, что Cache-Control: no-cache. Подробнее об этом поговорим во второй части.

Заголовок Date используется для хранения даты и времени запроса/ответа.

Заголовок Upgrade используется для изменения протокола.

Transfer-Encoding предназначается для разделения ответа на несколько фрагментов с помощью Transfer-Encoding: chunked. Это нововведение версии HTTP/1.1.

Заголовки сущностей

В заголовках сущностей передаётся мета-информация контента:

Entity-header = Allow | Content-Encoding | Content-Language | Content-Length | Content-Location | Content-MD5 | Content-Range | Content-Type | Expires | Last-Modified

Все заголовки с префиксом Content- предоставляют информацию о структуре, кодировке и размере тела сообщения.

Заголовок Expires содержит время и дату истечения сущности. Значение “never expires” означает время + 1 код с текущего момента. Last-Modified содержит время и дату последнего изменения сущности.

С помощью данных заголовков, можно задать нужную для ваших задач информацию.

Формат запроса

Запрос выглядит примерно так:

Request-Line = Method SP URI SP HTTP-Version CRLF Method = "OPTIONS" | "HEAD" | "GET" | "POST" | "PUT" | "DELETE" | "TRACE"

SP - это разделитель между токенами. Версия HTTP указывается в HTTP-Version. Реальный запрос выглядит так:

GET /articles/http-basics HTTP/1.1 Host: www.articles.com Connection: keep-alive Cache-Control: no-cache Pragma: no-cache Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Список возможных заголовков запроса:

Request-header = Accept | Accept-Charset | Accept-Encoding | Accept-Language | Authorization | Expect | From | Host | If-Match | If-Modified-Since | If-None-Match | If-Range | If-Unmodified-Since | Max-Forwards | Proxy-Authorization | Range | Referer | TE | User-Agent

В заголовке Accept определяется поддерживаемые mime типы, язык, кодировку символов. Заголовки From, Host, Referer и User-Agent содержат информацию о клиенте. Префиксы If- предназначены для создания условий. Если условие не прошло, то возникнет ошибка 304 Not Modified.

Формат ответа

Формат ответа отличается только статусом и рядом заголовков. Статус выглядит так:

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

  • HTTP версия
  • Код статуса
  • Сообщение статуса, понятное для человека

Обычный статус выглядит примерно так:

HTTP/1.1 200 OK

Заголовки ответа могут быть следующими:

Response-header = Accept-Ranges | Age | ETag | Location | Proxy-Authenticate | Retry-After | Server | Vary | WWW-Authenticate

  • Age время в секундах, когда сообщение было создано на сервере.
  • ETag MD5 сущности для проверки изменений и модификаций ответа.
  • Location используется для перенаправления и содержит новый URL адрес.
  • Server определяет сервер, где было сформирован ответ.

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

Инструменты для определения HTTP трафика

Существует множество инструментов для мониторинга HTTP трафика. Вот несколько из них:

Наиболее часто используемый - это Chrome Developers Tools:

Если говорить об отладчике, можно воспользоваться Fiddler :

Для отслеживания HTTP трафика вам потребуется curl, tcpdump и tshark.

Библиотеки для работы с HTTP - jQuery AJAX

Поскольку jQuery очень популярен, в нём также есть инструментарий для обработки HTTP ответов при AJAX запросах. Информацию о jQuery.ajax(settings) можете найти на официальном сайте .

Передав объект настроек (settings), а также воспользовавшись функцией обратного вызова beforeSend, мы можем задать заголовки запроса, с помощью метода setRequestHeader().

$.ajax({ url: "http://www.articles.com/latest", type: "GET", beforeSend: function (jqXHR) { jqXHR.setRequestHeader("Accepts-Language", "en-US,en"); } });

Если хотите обработать статус запроса, то это можно сделать так:

$.ajax({ statusCode: { 404: function() { alert("page not found"); } } });

Итог

Вот такой вот он, тур по основам протокола HTTP. Во второй части будет ещё больше интересных фактов и примеров.



 

Пожалуйста, поделитесь этим материалом в социальных сетях, если он оказался полезен!