Как отправить http запрос в браузере

Обновлено: 07.07.2024

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

Тим Бернес-Ли, Всемирная паутина: Очень короткая личная история

Протокол

Сервер отвечает по тому же соединению:

<!doctype html>
… остаток документа

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

Информация, отправленная клиентом, называется запросом. Он начинается со строки:

Первое слово – метод запроса. GET означает, что нам нужно получить определённый ресурс. Другие распространённые методы – DELETE для удаления, PUT для замещения и POST для отправки информации. Заметьте, что сервер не обязан выполнять каждый полученный запрос. Если вы выберете случайный сайт и скажете ему DELETE главную страницу – он, скорее всего, откажется.

Ответ сервера также начинается с версии протокола, за которой идёт статус ответа – сначала код из трёх цифр, затем строчка.

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

Content-Length: 65585
Content-Type: text/html
Last-Modified: Wed, 09 Apr 2014 10:48:09 GMT

Тут определяется размер и тип документа, полученного в ответ. В данном случае это HTML-документ размером 65’585 байт. Также тут указано, когда документ был изменён последний раз.

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

Как мы видели в примере, браузер отправляет запрос, когда мы вводим URL в адресную строку. Когда в полученном HTML документе содержатся упоминания других файлов, такие, как картинки или файлы JavaScript, они тоже запрашиваются с сервера.

Веб-сайт средней руки легко может содержать от 10 до 200 ресурсов. Чтобы иметь возможность запросить их побыстрее, браузеры делают несколько запросов одновременно, а не ждут окончания запросов одного за другим. Такие документы всегда запрашиваются через запросы GET.

На страницах HTML могут быть формы, которые позволяют пользователям вписывать информацию и отправлять её на сервер. Вот пример формы:

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

В следующей главе мы вернёмся к формам и поговорим про то, как мы можем делать их при помощи JavaScript.

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

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

Можно получить из объекта response и другую информацию. Код статуса доступен в свойстве status, а текст статуса – в statusText. Заголовки можно прочесть из getResponseHeader.

Названия заголовков не чувствительны к регистру. Они обычно пишутся с заглавной буквы в начале каждого слова, например “Content-Type”, но “content-type” или “cOnTeNt-TyPe” будут описывать один и тот же заголовок.

Браузер сам добавит некоторые заголовки, такие, как “Host” и другие, которые нужны серверу, чтобы вычислить размер тела. Но вы можете добавлять свои собственные заголовки методом setRequestHeader. Это нужно для особых случаев и требует содействия сервера, к которому вы обращаетесь – он волен игнорировать заголовки, которые он не умеет обрабатывать.

Асинхронные запросы

В примере запрос был окончен, когда заканчивается вызов send. Это удобно потому, что свойства вроде responseText становятся доступными сразу. Но это значит, что программа наша будет ожидать, пока браузер и сервер общаются меж собой. При плохой связи, слабом сервере или большом файле это может занять длительное время. Это плохо ещё и потому, что никакие обработчики событий не сработают, пока программа находится в режиме ожидания – документ перестанет реагировать на действия пользователя.

Если третьим аргументом open мы передадим true, запрос будет асинхронным. Это значит, что при вызове send запрос ставится в очередь на отправку. Программа продолжает работать, а браузер позаботиться об отправке и получении данных в фоне.

Но пока запрос обрабатывается, мы не получим ответ. Нам нужен механизм оповещения о том, что данные поступили и готовы. Для этого нам нужно будет слушать событие “load”.

Так же, как вызов requestAnimationFrame в главе 15, этот код вынуждает нас использовать асинхронный стиль программирования, оборачивая в функцию тот код, который должен быть выполнен после запроса, и устраивая вызов этой функции в нужное время. Мы вернёмся к этому позже.

Получение данных XML

Мы можем получить такой файл следующим образом:

Документы XML можно использовать для обмена с сервером структурированной информацией. Их форма – вложенные теги – хорошо подходит для хранения большинства данных, ну или по крайней мере лучше, чем текстовые файлы. Интерфейс DOM неуклюж в плане извлечения информации, и XML документы получаются довольно многословными. Обычно лучше общаться при помощи данных в формате JSON, которые проще читать и писать – как программам, так и людям.

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

Абстрагируем запросы

В главе 10 в нашей реализации модульной системы AMD мы использовали гипотетическую функцию backgroundReadFile. Она принимала имя файла и функцию, и вызывала эту функцию после прочтения содержимого файла. Вот простая реализация этой функции:

Аргумент callback (обратный вызов) – термин, часто использующийся для описания подобных функций. Функция обратного вызова передаётся в другой код, чтобы он мог позвать нас обратно позже.

Основная проблема с приведённой обёрткой – обработка ошибок. Когда запрос возвращает код статуса, обозначающий ошибку (от 400 и выше), он ничего не делает. В некоторых случаях это нормально, но представьте, что мы поставили индикатор загрузки на странице, показывающий, что мы получаем информацию. Если запрос не удался, потому что сервер упал или соединение прервано, страница будет делать вид, что она чем-то занята. Пользователь подождёт немного, потом ему надоест и он решит, что сайт какой-то дурацкий.

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

Чтобы обрабатывать неудачные запросы, придётся передавать дополнительную функцию в нашу обёртку, и вызывать её в случае проблем. Другой вариант – использовать соглашение, что если запрос не удался, то в функцию обратного вызова передаётся дополнительный аргумент с описанием проблемы. Пример:

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

Код, использующий getURL, должен проверять не возвращена ли ошибка, и обрабатывать её, если она есть.

С исключениями это не помогает. Когда мы совершаем последовательно несколько асинхронных действий, исключение в любой точке цепочки в любом случае (если только вы не обернули каждый обработчик в свой блок try/catch) вывалится на верхнем уровне и прервёт всю цепочку.

Обещания

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

Предпринималось множество попыток решить эту проблему дополнительными абстракциями. Одна из наиболее удачных попыток называется обещаниями (promises). Обещания оборачивают асинхронное действие в объект, который может передаваться и которому нужно сделать какие-то вещи, когда действие завершается или не удаётся. Такой интерфейс уже стал частью текущей версии JavaScript, а для старых версий его можно использовать в виде библиотеки.

Для создания объекта promises мы вызываем конструктор Promise, задавая ему функцию инициализации асинхронного действия. Конструктор вызывает эту функцию и передаёт ей два аргумента, которые сами также являются функциями. Первая должна вызываться в удачном случае, другая – в неудачном.

И вот наша обёртка для запросов GET, которая на этот раз возвращает обещание. Теперь мы просто назовём его get.

Заметьте, что интерфейс к самой функции упростился. Мы передаём ей URL, а она возвращает обещание. Оно работает как обработчик для выходных данных запроса. У него есть метод then, который вызывается с двумя функциями: одной для обработки успеха, другой – для неудачи.

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

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

Значит, вы можете использовать then для изменения результата обещания. К примеру, следующая функция возвращает обещание, чей результат – содержимое с данного URL, разобранное как JSON:

Последний вызов then не обозначил обработчик неудач. Это допустимо. Ошибка будет передана в обещание, возвращаемое через then, а ведь это нам и надо – getJSON не знает, что делать, когда что-то идёт не так, но есть надежда, что вызывающий её код это знает.

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

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

При создании системы, в которой программа на JavaScript в браузере (клиентская) общается с серверной программой, можно использовать несколько вариантов моделирования такого общения.

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

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

Упражнения

Согласование содержания (content negotiation)

Наконец, попробуйте запросить содержимое типа application/rainbows+unicorns и посмотрите, что произойдёт.

Ожидание нескольких обещаний

У конструктора Promise есть метод all, который, получая массив обещаний, возвращает обещание, которое ждёт завершения всех указанных в массиве обещаний. Затем он выдаёт успешный результат и возвращает массив с результатами. Если какие-то из обещаний в массиве завершились неудачно, общее обещание также возвращает неудачу (со значением неудавшегося обещания из массива).

Попробуйте сделать что-либо подобное, написав функцию all.

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

Предположим, что он ввёл в адресной строке следующее:

Для этого вы можете воспользоваться любой подходящей утилитой командной строки. Например, telnet:

Например (такая стартовая строка может указывать на то, что запрашивается главная страница сайта):

URI (Uniform Resource Identifier, унифицированный идентификатор ресурса) — путь до конкретного ресурса (например, документа), над которым необходимо осуществить операцию (например, в случае использования метода GET подразумевается получение ресурса). Некоторые запросы могут не относиться к какому-либо ресурсу, в этом случае вместо URI в стартовую строку может быть добавлена звёздочка (астериск, символ «*»). Например, это может быть запрос, который относится к самому веб-серверу, а не какому-либо конкретному ресурсу. В этом случае стартовая строка может выглядеть так:

При этом учитывайте, что для переноса строки следует использовать символ возврата каретки (Carriage Return), за которым следует символ перевода строки (Line Feed). После объявления последнего заголовка последовательность символов для переноса строки добавляется дважды.

Как прочитать ответ?

Стартовая строка ответа имеет следующую структуру:

Версия протокола здесь задаётся так же, как в запросе.

Пояснение к коду состояния (Reason Phrase) — текстовое (но не включающее символы CR и LF) пояснение к коду ответа, предназначено для упрощения чтения ответа человеком. Пояснение может не учитываться клиентским программным обеспечением, а также может отличаться от стандартного в некоторых реализациях серверного ПО.

После стартовой строки следуют заголовки, а также тело ответа. Например:


Тело ответа следует через два переноса строки после последнего заголовка. Для определения окончания тела ответа используется значение заголовка Content-Length (в данном случае ответ содержит 7 восьмеричных байтов: слово «Wisdom» и символ переноса строки).

Но вот по тому запросу, который мы составили ранее, веб-сервер вернёт ответ не с кодом 200, а с кодом 302. Таким образом он сообщает клиенту о том, что обращаться к данному ресурсу на данный момент нужно по другому адресу.

В ответ на этот запрос веб-сервер Хабрахабра уже выдаст ответ с кодом 200 и достаточно большой документ в формате HTML.

Если вы уже успели вжиться в роль, то можете теперь прочитать полученный от сервера HTML-код, взять карандаш и блокнот, и нарисовать профайл Ализара — в принципе, именно этим бы на вашем месте браузер сейчас и занялся.

А что с безопасностью?

А есть дополнительные возможности?

Что-то ещё, кстати, используют?

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

На данный момент поддержка протокола SPDY есть в браузерах Firefox, Chromium/Chrome, Opera, Internet Exporer и Amazon Silk.

И что, всё?

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

Предположим, что он ввёл в адресной строке следующее:

Для этого вы можете воспользоваться любой подходящей утилитой командной строки. Например, telnet:

Например (такая стартовая строка может указывать на то, что запрашивается главная страница сайта):

URI (Uniform Resource Identifier, унифицированный идентификатор ресурса) — путь до конкретного ресурса (например, документа), над которым необходимо осуществить операцию (например, в случае использования метода GET подразумевается получение ресурса). Некоторые запросы могут не относиться к какому-либо ресурсу, в этом случае вместо URI в стартовую строку может быть добавлена звёздочка (астериск, символ «*»). Например, это может быть запрос, который относится к самому веб-серверу, а не какому-либо конкретному ресурсу. В этом случае стартовая строка может выглядеть так:

При этом учитывайте, что для переноса строки следует использовать символ возврата каретки (Carriage Return), за которым следует символ перевода строки (Line Feed). После объявления последнего заголовка последовательность символов для переноса строки добавляется дважды.

Как прочитать ответ?

Стартовая строка ответа имеет следующую структуру:

Версия протокола здесь задаётся так же, как в запросе.

Пояснение к коду состояния (Reason Phrase) — текстовое (но не включающее символы CR и LF) пояснение к коду ответа, предназначено для упрощения чтения ответа человеком. Пояснение может не учитываться клиентским программным обеспечением, а также может отличаться от стандартного в некоторых реализациях серверного ПО.

После стартовой строки следуют заголовки, а также тело ответа. Например:


Тело ответа следует через два переноса строки после последнего заголовка. Для определения окончания тела ответа используется значение заголовка Content-Length (в данном случае ответ содержит 7 восьмеричных байтов: слово «Wisdom» и символ переноса строки).

Но вот по тому запросу, который мы составили ранее, веб-сервер вернёт ответ не с кодом 200, а с кодом 302. Таким образом он сообщает клиенту о том, что обращаться к данному ресурсу на данный момент нужно по другому адресу.

В ответ на этот запрос веб-сервер Хабрахабра уже выдаст ответ с кодом 200 и достаточно большой документ в формате HTML.

Если вы уже успели вжиться в роль, то можете теперь прочитать полученный от сервера HTML-код, взять карандаш и блокнот, и нарисовать профайл Ализара — в принципе, именно этим бы на вашем месте браузер сейчас и занялся.

А что с безопасностью?

А есть дополнительные возможности?

Что-то ещё, кстати, используют?

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

На данный момент поддержка протокола SPDY есть в браузерах Firefox, Chromium/Chrome, Opera, Internet Exporer и Amazon Silk.

И что, всё?

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

Почему REST?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

DELETE

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

200 OK

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

201 Created

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

400 Bad Request

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

404 Not Found

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

401 Unauthorized

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

405 Method Not Allowed

409 Conflict

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

500 Internal Server Error

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

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

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

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

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

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

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

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

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

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

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

Заключение

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

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

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




Пример

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







  • getallheaders() получает запросы headers. Вы можете использовать массив $_SERVER.
  • headers_list() получает отзывы headers.

Далее в этой статье мы увидим примеры кода в PHP.




  • "method" указывает, какой это запрос. Наиболее распространённые методы GET, POST и HEAD.
  • "path" , как правило, является частью URL-адреса, который идёт после host (домена). Например, если запрос "https://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/" , часть path будет "/tutorials/other/top-20-mysql-best-practices/".
  • Часть "protocol" содержит "HTTP" и версию, которая обычно 1.1 в современных браузерах.

Остальная часть запроса содержит HTTP headers как пары "Name: Value" в каждой строке. Они содержат различную информацию о HTTP-запросе и вашем браузере. Например, строка "User-Agent" предоставляет информацию о версии браузера и операционной системе, которую вы используете. "Accept-Encoding" сообщает серверу, может ли ваш браузер принимать сжатый output, например gzip.

И вы всё равно получите правильный ответ от веб-сервера.

Методы запроса

Три наиболее часто используемых метода запроса: GET, POST и HEAD. Вы, вероятно, уже знакомы с первыми двумя, начиная с написания html-форм.

GET: получение документа

Это основной метод, используемый для извлечения html, изображений, JavaScript, CSS и т. д. С использованием этого метода запрошено большинство данных, загружаемых в ваш браузер.

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

Веб-формы можно настроить под метод GET. Вот пример.

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

POST: отправка данных на сервер

Даже если вы можете отправлять данные на сервер с помощью GET и строки запроса, во многих случаях POST будет предпочтительнее. Отправка больших объёмов данных с помощью GET нецелесообразна и имеет ограничения.

Запросы POST чаще всего отправляются веб-формами. Давайте изменим предыдущий пример формы на метод POST.

Здесь нужно отметить три важных момента:

  • Путь в первой строке просто /foo.php, и больше нет строки запроса.
  • Добавлены заголовки Content-Type и Content-Length, которые предоставляют информацию об отправляемых данных.
  • Все данные теперь отправляются после заголовков, в том же формате, что и строка запроса.

Запросы POST метода также могут быть сделаны через AJAX, приложения, cURL и т. д. И все формы загрузки файлов необходимы для использования метода POST.

HEAD: получение информации заголовка

С помощью этого метода браузер может проверить, был ли документ изменён для целей caching. Он также может проверить, существует ли документ вообще.

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




Опять же, большинство этих headers на самом деле являются необязательными.

  • 200 используются для успешных запросов.
  • 300 для перенаправления.
  • 400 используются, если возникла проблема с запросом.
  • 500 используются, если возникла проблема с сервером.

200 OK

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

206 Partial Content

Если приложение запрашивает только диапазон запрошенного файла, возвращается код 206.

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

404 Not Found




Когда запрашиваемая страница или файл не найдена, сервер отправляет код ответа 404.

401 Unauthorized

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







403 Forbidden

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




Существуют другие способы блокировки доступа и 403 могут быть отправлены. Например, вы можете блокировать по IP-адресу с помощью некоторых директив htaccess.

302 (or 307) Moved Temporarily & 301 Moved Permanently

Эти два кода используются для перенаправления браузера. Например, когда вы используете службу сокращения URL, такую как bit.ly, именно так они перенаправляют людей, которые идут по ссылке.

500 Internal Server Error




Complete List

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

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

User-Agent

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

  • Имя и версия браузера.
  • Название и версия операционной системы.
  • Язык по умолчанию.

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

Accept-Language

Он может содержать несколько языков, разделённых запятыми. Первый - это предпочтительный язык, и каждый из перечисленных языков может иметь значение «q», которое представляет собой оценку предпочтения пользователя для языка (min. 0 max. 1).

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

Accept-Encoding

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

If-Modified-Since

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

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

Cookie

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

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

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

Referer

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

Authorization

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

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

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

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

Cache-Control

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

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

Content-Type

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

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

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

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

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

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

Content-Disposition

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

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




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

Content-Length

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

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

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




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

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




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

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

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

Last-Modified

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

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

Location

Set-Cookie

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

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

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

WWW-Authenticate

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




В руководстве PHP есть section, в котором приведены образцы кода, как это сделать в PHP.

Content-Encoding

Этот header обычно устанавливается, когда возвращаемое содержимое сжимается.

В PHP, если вы используете функцию обратного вызова ob_gzhandler(), она будет автоматически установлена.

Заключение

Читайте также: