Пользователь
0,0
рейтинг
2 сентября 2008 в 21:34

Разработка → Архитектура REST

Введение


В русскоязычной части Интернета присутствует большое количество статей, посвященных веб-службам на основе SOAP и XML-RPC, но почему-то почти ничего нет про вполне заслуживающую внимания (но менее распространенную) архитектуру RESТ.

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


Что такое REST


REST (Representational state transfer) – это стиль архитектуры программного обеспечения для распределенных систем, таких как World Wide Web, который, как правило, используется для построения веб-служб. Термин REST был введен в 2000 году Роем Филдингом, одним из авторов HTTP-протокола. Системы, поддерживающие REST, называются RESTful-системами.

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

А теперь тоже самое более наглядно:

Отсутствие дополнительных внутренних прослоек означает передачу данных в том же виде, что и сами данные. Т.е. мы не заворачиваем данные в XML, как это делает SOAP и XML-RPC, не используем AMF, как это делает Flash и т.д. Просто отдаем сами данные.

Каждая единица информации однозначно определяется URL – это значит, что URL по сути является первичным ключом для единицы данных. Т.е. например третья книга с книжной полки будет иметь вид /book/3, а 35 страница в этой книге — /book/3/page/35. Отсюда и получается строго заданный формат. Причем совершенно не имеет значения, в каком формате находятся данные по адресу /book/3/page/35 – это может быть и HTML, и отсканированная копия в виде jpeg-файла, и документ Microsoft Word.

Как происходит управление информацией сервиса – это целиком и полностью основывается на протоколе передачи данных. Наиболее распространенный протокол конечно же HTTP. Так вот, для HTTP действие над данными задается с помощью методов: GET (получить), PUT (добавить, заменить), POST (добавить, изменить, удалить), DELETE (удалить). Таким образом, действия CRUD (Create-Read-Updtae-Delete) могут выполняться как со всеми 4-мя методами, так и только с помощью GET и POST.

Вот как это будет выглядеть на примере:

GET /book/ — получить список всех книг
GET /book/3/ — получить книгу номер 3
PUT /book/ — добавить книгу (данные в теле запроса)
POST /book/3 – изменить книгу (данные в теле запроса)
DELETE /book/3 – удалить книгу

ВАЖНОЕ ДОПОЛНЕНИЕ: Существуют так называемые REST-Patterns, которые различаются связыванием HTTP-методов с тем, что они делают. В частности, разные паттерны по-разному рассматривают POST и PUT. Однако, PUT предназначен для создания, реплейса или апдейта, для POST это не определено (The POST operation is very generic and no specific meaning can be attached to it). Поэтому мой пример будет правильным и в таком виде, и в виде если поменять местами POST и PUT.

Вообще, POST может использоваться одновременно для всех действий изменения:
POST /book/ – добавить книгу (данные в теле запроса)
POST /book/3 – изменить книгу (данные в теле запроса)
POST /book/3 – удалить книгу (тело запроса пустое)

Это позволяет иногда обходить неприятные моменты, связанные с неприятием PUT и DELETE.

Использование REST для построения Web-сервисов.


Как известно, web-сервис – это приложение работающее в World Wide Web и доступ к которому предоставляется по HTTP-протоколу, а обмен информации идет с помощью формата XML. Следовательно, формат данных передаваемых в теле запроса будет всегда XML.

Для каждой единицы информации (info) определяется 5 действий. А именно:

GET /info/ (Index) – получает список всех объектов. Как правило, это упрощенный список, т.е. содержащий только поля идентификатора и названия объекта, без остальных данных.

GET /info/{id} (View) – получает полную информацию о объекте.

PUT /info/ или POST /info/ (Create) – создает новый объект. Данные передаются в теле запроса без применения кодирования, даже urlencode. В PHP тело запроса может быть получено таким способом:

function getBody() {
if (!isset($HTTP_RAW_POST_DATA))
$HTTP_RAW_POST_DATA = file_get_contents("php://input");
return $HTTP_RAW_POST_DATA;
}


POST /info/{id} или PUT /info/{id} (Edit) – изменяет данные с идентификатором {id}, возможно заменяет их. Данные так же передаются в теле запроса, но в отличие от PUT здесь есть некоторый нюанс. Дело в том, что POST-запрос подразумевает наличие urldecoded-post-data. Т.е. если не применять кодирования – это нарушение стандарта. Тут кто как хочет – некоторые не обращают внимания на стандарт, некоторые используют какую-нибудь post-переменную.

DELETE /info/{id} (Delete) – удаляет данные с идентификатором {id}.

Еще раз отмечу, что в нашем примере /info/ — может и базироваться на какой-то другой информации, что может быть (и должно) быть отражено в URL:

/data/4/otherdata/6/info/3/ … и тому подобное.

Какие можно сделать из этого выводы:

Как видно, в архитектура REST очень проста в плане использования. По виду пришедшего запроса сразу можно определить, что он делает, не разбираясь в форматах (в отличие от SOAP, XML-RPC). Данные передаются без применения дополнительных слоев, поэтому REST считается менее ресурсоемким, поскольку не надо парсить запрос чтоб понять что он должен сделать и не надо переводить данные из одного формата в другой.

Практическое применение.


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

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

Ссылки по теме:


http://en.wikipedia.org/wiki/REST
http://ru.wikipedia.org/wiki/Веб-служба
Артемий @enartemy
карма
269,6
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (72)

  • +2
    Хорошая статья для того чтобы начать изучение архитектуры, спасибо
  • 0
    >Следовательно, формат данных передаваемых в теле запроса будет всегда XML.
    эт не совсем верно. какой формат захочешь — такой и будет, не всегда xml подходит
    • +3
      «Веб-служба, веб-сервис (англ. web service) — программная система, идентифицируемая строкой URI, чьи общедоступные интерфейсы определены на языке XML» — это из википедии.

      «Классическая» служба строится именно на XML. Конечно, можно использовать и json и другие форматы, но это скорее новомодная практика, нежели стандарт.
      • 0
        :) Замешкался я с комментарием.
      • –26
        хмл ты фиг получишь с другого домена в отличие от яваскрипта…
        • 0
          Не согласен. Аргументируйте.
          • 0
            проксирование через свой сервер — фиговый вариант.
            • 0
              Вообще то один из вариантов использования кросс доменного запроса это работа через элемент script. Какая разница указано в src. И вообще за кросс доменом будущее ;)
              • 0
                и как ты собираешься получать хмл через элемент скрипт?
                • +1
                  JS обертка делается для данных которые получают. Может статью сделаю на эту тему, после предварительных исследований. А тема очень важная.
                  • –4
                    «js обёртка» — это и есть «новомодный json». только данные зачем-то передаются виде одной-единственной json-строки, а не в виде дерева объектов.
                • –2
                  var myXML = 'here';

                  ;)
                  • 0
                    выкачай снаяала вот этот хмл: habrahabr.ru/rss/blogs/webdev/38730/fb8d8890e4869cbf60a77b2e9832b26d/
                    а потом улыбайся
                  • 0
                    1. закладка долго была открыта, поэтому задержался с ответом который потерял смысл после слов m007
                    2. парсер скушал XML-теги вокруг here :«)

                    «js обёртка» — это и есть «новомодный json». только данные зачем-то передаются виде одной-единственной json-строки, а не в виде дерева объектов.

                    каков вопрос (»как ты собираешься получать хмл« через элемент скрипт) таков ответ. XML получить не проблема, вопрос лишь в том нужно ли это делать ;)
    • 0
      Эмм… «Ортодоксальный» веб-сервис, если не изменяет память, предполагает использование формата XML.
  • +2
    не грех упомянуть rails которые используют rest поумолчанию
    • +1
      Тогда надо упоминать вообще все MVC-фреймворки. Многие из них используют REST. Тот же CakePhp содержит специальный функционал для этого. Уверен, остальные тоже.
      • +1
        Мне кажется… что конкретно CakePHP унаследовал это у Rails… как и другие ( не все! )… по-этому человек говорит о рельсах. Ноу Холивар! просто объективно смотрю на вещи.
        • 0
          И что он унаследовал?
          Просто только rails REST выставляет как фичу, а придумали далеко не они. Кроме того, REST все описывает достаточно конткретно, поэтому реализации и будут похожи
  • +3
    Кстати, один из примеров использования REST — Assembla — хостинг для проектов. К слову сказать, удобный: SVN, Trac, Wiki, Scrum и прочие вкусности. Базовый аккаунт пока бесплатен.
  • –3
    мне кажется, это применимо для небольших или несложных решений
    • 0
      Кстати, интерсно. На этом хостинге PUT и POST зачем-то поменяли местами. Т.е. POST используется для создания, а PUT для изменения. Вообще это противорчечит архитектуре, и мне соврешенно непонятно зачем это сделано.
      • 0
        ru.wikipedia.org/wiki/HTTP#POST
      • 0
        это в статье не правильно написано
        • 0
          en.wikipedia.org/wiki/REST#RESTful_example:_the_World_Wide_Web

          + я точно знаю, что в CakePhp для edit используется POST.

          Так что я думаю, что вы ошибаетесь.
    • +1
      Это применимо для чего угодно, главное знать как применять.
  • 0
    Если говорить об внутренних вебсервисах проекта, реализующих сервисно-объектную архитектуру, то xml однозначно проигрывает. Имхо, в СОА удобней и эффективней использовать, что-то легковесное и быстрое, например jsonrpc, rest или протоколы обмена данными по типу google buffer protocol или trifft
  • –2
    REST это не архитектура, а метод. Фактически он так в HTML формах и называется — method.

    Приписывать четырём методам свойства «архитектуры» из которых реально в браузерах только два поддерживаются — поспешно.
    • +1
      Вы не поняли темы. method в форме, это всего лишь метод передачи запроса. Сама архитектура REST исповедует разделение на ресурсы. Все есть ресурс. Как в ООП — все есть объект. И каждый ресурс имеет свой адрес (url). Т.е. когда вы запрашиваете книгу (как в статье) по урлу и передаете GETом параметры через вопросик, это уже не REST. REST предполагает, что книга это ресурс и у нее есть свой адрес. Методов GET, POST, PUT и DELETE достаточно для работы с такой моделью.
      • 0
        Я понимаю что это предполагает «всё объект» и я сам использовал REST в java.

        Может мы по разному понимаем определение «архитектуры», помоему это нечто фундаментальное на чём основывается проект. Это может быть язык, framework как его расширение, наконец совокупность используемых методов.

        REST же практически используется как правило только как интерфейс — для общения с внешними сервисами, подобно SOAP и XML-RPC, просто будучи значительно проще имеет большую распространённость (благодаря GET и POST). Называть этод метод платформой и уж тем более архитектурой — глупо, если конечно вы не пишете приложение где этод метод лежит в основе всего, но это опять же проблематично потому что браузеры не поддерживают PUT и DELETE.
        • 0
          Соглашусь, что REST в каком-то смысле сложно обозвать архитектурой.
          Это скорее подход. Как ООП ;)
          Но, с другой стороны, чтобы в полной мере реализовать REST, понадобится разработать под это дело архитектуру. Которую потом придется обозвать REST-архитектурой.
          Так что считаю спорить о том, является ли REST архитектурой или не является, пустым делом ;)
          • +1
            Вы путаете вариант реализации с основой. HTTP GET-PUT-POST-DELETE это реализация CRUD для HTTP-протокола. Она наиболее часто используется, поэтому и возникает путаница.

            REST — это архитектeра. Она строится на принципах, которые вы сами же и назвали. Но url — это именно universal resource locator, универсальный идентификатор ресурса, а не ссылка в интернете. Вобщем, если совсем просто согласно REST — в заголовке — что сделать и с каким ресурсом, а данные в теле запроса. А какой протокол используется — дело десятое.
            • 0
              Что я ничего не понял, что вы тут нагородили )
              «HTTP GET-PUT-POST-DELETE это реализация CRUD для HTTP-протокола.» согласен.
              «Она наиболее часто используется, поэтому и возникает путаница.» Какая путаница? С чем?

              «Но url — это именно universal resource locator, универсальный идентификатор ресурса, а не ссылка в интернете.» Это где я URL ссылкой обозвал *осматривается* :)
              • 0
                Какая путаница? С чем? — c тем что HTTP GET-PUT-POST-DELETE — это реализация REST, но не REST во всей своей сущности.

                «Это где я URL ссылкой обозвал» — не называли. Это я для сведения просто написал, а вы приняли на свой счет. :-)
                • +2
                  Да бросьте. Тут каждый второй ни разу не слышал про REST :)
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
  • 0
    Сори, html-редактор глюканул.
    hinchcliffe.org/img/restinteractionvisual.png
  • 0
    Человек, который это писал молодец. Но, зачем было сюда приплетать AMF.
    AMF — это формат передачи данных. Вся его соль в том, что он бинарный (меньше объем передаваемых данных) и позволяет передавать типизированные данные. Используя разные прослойки (например AMFPHP) вы можете работать на стороне сервера с объектами, передавать их по протоколу и во Flash получить типизированный объект. В итоге, не надо ничего парсить, ничего выдумывать. Просто тупо вызываем необходимый нам метод.
    Кстати, AMF работает быстрее, чем ручное распаршивание данных.

    Как эффективно (при минимальных затратах) прикрутить REST во Flash я не знаю. Буду рад, если кто-нибудь прояснит.
    • 0
      Во флеше можно получить непосредственно данные из тела запроса? GET и POST можете послать? XML можете распарсить? Если да, то больше ничего не надо.

      Но для флеша AMF удобнее будет, всё же.
  • +4
    REST is not about url design only, REST is not opposite to RPC (even XML-RPC), REST is about using HTTP in natural way, without any unreasonable overhead
  • +4
    Почему-то REST всем нравится. Почему-то каждый, кто открывает его для себя наполняется энтузиазмом и с криком «Так правильно, да будет так!!!» бьет себя пяткой в грудь и обещает начать это дело использовать. Вот только на этом дело обычно и останавливается.
    REST призывает использовать HTTP по прямому назначению, ровно так, как он изначально задумывался, без всяких его расширений и перегрузок. Но в наших реалиях это мало возможно. Все стремятся использовать ЧПУ (красивые урлы, если кто не в курсе). Это хорошо, это дает возможность сказать, что каждый наш ресурс имеет урл, но это еще далеко от REST.

    Поясню. REST предполагает, что все есть ресурс. Таким образом, каждый комментарий к этой статье должен иметь свой URL и быть по нему доступен. И каждый коммент должен подгружаться отдельным запросом.
    Все как в ООП. Если у вашего объекта «магазин» есть метод «инвентарь», то инвентарь это тоже объект, и каждый предмет в инвентаре тоже есть объект, и загружается соответственно отдельно.
    Но с другой стороны REST на этом не настаивает. Вот жешь блин )))

    Короче. REST — это мечта, которая на практике не эффективна. Так же как красивый код и безупречная архитектура. Рано или поздно, станет тесно и не удобно.

    Кстати, такая вещь как cookie должна противоречить REST.

    Все сказанное сугубо IMHO. Конструктивные критика и комментарии приветствуются )))
    • +1
      >Кстати, такая вещь как cookie должна противоречить REST.

      объясните?
      • +1
        Cookie не нужны для идентификации ресурса, для этого служит URL. Все остальные данные должны передаваться методами POST и PUT.
        Cookie — это надстройка над HTTP протоколом, а это уже не REST по его же определению. Примерно так )
    • 0
      Подпишусь под каждым словом. От себя добавлю, может потому что использование REST непривычно. Сложно просто смотреть на вещи, если привык смотреть сложно. :-)
    • 0
      Абсолютно верно. Поставил бы плюс, да нечем.
      Добавлю еще, что ЧПУ все-таки играют некоторую роль в SEO (большую или малую — другой вопрос).
      Да и юзеру приятней видеть УРЛ вида www.theverybestshop.aa/catalog/notebooks/, чем безликое .../catalog/124 в тех же результатах поиска.
      • 0
        так никто не мешает использовать такой URI в REST
    • 0
      список комментариев тоже объект.

      ничто не мешает выполнить денормализацию на уровне представления, даже наоборот :)
      • 0
        Если список комментариев представлять как объект, то этот объект должен тогда включать в себя вообще все комментарии, иначе это уже фигня какая-то получится. Список комментариев это должен быть метод объекта «сообщение», который возвращает список объектов «комментарий».

        Но это все не важно в данном случае. Мы ведь обсуждаем идеальный вариант архитектуры с теоретической точки зрения. Т.е. денормализация в данном случае нам побоку. На практике это конечно будет по другому, но обсуждаем мы идеальный вариант. Как-то так ;)
  • –1
    Покажите мне место где описан «стандарт» под названием REST?
    C RPC все понятно www.xmlrpc.com/spec
    Еще, нафига вся эта канитель с запросами PUT и DELETE, любой нормальный сисадмин запретит вебсерверу принимать такие запросы.
    Скажете что имя метода передается в переменной method? Тогда зачем вся эта ширма и намеки на стандарт? Давайте так и будем говорить «на rest сервер всегда делается POST запрос в котором передается переменная method в котором мы указываем что именно хотим.
    • 0
      Причем тут стандарт, когда это архитектурный стиль?
      • 0
        Потому что реализация этого стиля лежит полностью на разработчике сервиса. Сторонним разработчикам нельзя будет просто назвать имена свои методов (или точнее Урлы) и сказать мол «нате пользуйтесь». И если нужно будет этот сервис сделать публичным то прийдется написать самом соответствующие библиотеки на разных языках программирования.
        • 0
          А его реализация и не лежит на разработчике. Стиль не надо реализовывать — его можно использовать или нет в своих сервисах. А о том, что REST имеет недостатки — это само собой. В отличие от «Classic Web Services», здесь нет WSDL и пользователи сервиса не могут получать метаданные от самого сервиса (в том числе обновления в наборах методов конечных точек), а вынуждены, как вариант, запрашивать их с некоего стороннего сервиса.
          Однако, как раз таки «Урлы» назвать можно будет, как раз сказав «нате пользуйтесь». Однако параллельно с этим нужно будет сообщить правила работы с сервисом.

          Архитектура REST прекрасно показывает себя в одних приложениях, SOAP и WSDL — в других. Причем, последнее — более старое и зрелое, и более, так сказать, Enterprise-ready для сложных систем.

          А еще насчет REST надо сказать, что крайне редко удается следовать концепции «pure REST», то есть с точно ограниченным количеством методов конечной точки и в точном соответствии с общими правилами работы с сервисами (включая форматы).
    • 0
      это не стандарт, это скорее сборник рекомендаций
  • 0
    Класс, удивительно, что прежде эта тема не затрагивалась на Хабре
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Как оказалось, большая проблема найти хостера, который разрешает доступ к HTTP_RAW_POST_DATA.

    Посему «PUT /info/ (Create) — Данные передаются в теле запроса без применения кодирования» становится неразрешенным действием. Так что REST доступент только профи, которые могут себе позволить содержать выделенный сервер, чтобы настроить его как надо.
    • 0
      $HTTP_RAW_POST_DATA = file_get_contents(«php://input»); — это тоже не проходит?
      • 0
        Нет, зачастую обращения к url вида «php:» вообще отключены. И это на платных хостингах. Я упарился себе хостинг искать, на котором бы флешевый ролик принимал XML в чистом виде.
        • 0
          http_get_request_body (), если pecl http установлен?

          Пишите в саппорт хостинга. Это не правильно.
  • 0
    прошу не ругать, но объясните на пальцах пожалуйста, как при такой архитектуре мы будем идентифицировать пользователя
    • 0
      Куки, например.
  • 0
    По-моему, автор жестоко перепутал POST и PUT. POST должен создавать новые ресурсы, а PUT — обновлять их.
    • 0
      Вы правы в некоторой степени. См. ВАЖНОЕ ДОПОЛНЕНИЕ в статье.
  • 0
    хочу узнать побольше про REST,
    подскажите пожалуйста

    а как может выглядеть url get запроса скажем, для получения комментариев данного топика
    если надо получить скажем за раз 20 или 50 штук (типа limit 50 offset 100)

    habrahabr.ru/blogs/webdev/38730/comments/?
    • 0
      Вас никто не ограничивает в ссылке. Как хотите:

      GET /info/limit/20/offset/50
      • 0
        спасибо… я просто думал может есть какой-то общепринятый вариант…
        это ведь стандрартная вещь — получить N элементов списка… ведь все выводить не всегда реально,
        если их более 1000
  • 0
    У меня есть вопрос, а что если нам надо сделать удаление нескольких элементов, с ид например 15, 27 и 102, то как должна выглядеть ссылка или как должна сабмититса форма? не пойму.
    • 0
      DELETE /items/15;27;102
    • 0
      По-моему в статье сделано одно ключевое упущение. Что делает ее в общем-то неправильной и что вынудило автора написать «важное дополнение», которое в общем-то не изменило ситуации.

      Важно понимать что PUT — идемпотентный (idempotent) метод (также как и GET). Иными словами один и тот же запрос должен иметь один и тот же результат в независимости от количества повторений.

      Методы же POST и DELETE такими не являются. POST должен каждый раз добавлять данные в коллекцию, либо к объекту. DELETE — уничтожает объект или данные, два раза уничтожить одно и то же нельзя.

      Итак, когда же использовать POST, а когда PUT?
      При добавлении, вы добавляете данные и с заданным ID?
      Да: «PUT /items/3» — в этом случае мы жестко задали, что хотим создать элемент c ID = /items/3
      Нет: «POST /items/» — добавит новый item в коллекцию items, ID будет назначен автоматически следующим по счету

      Если вы обновляете существующие данные, то однозначно:
      «PUT /items/3» — обновит элемент с ID = /items/3
  • 0
    Говорят, грядет http 1.2. И, говорят, REST будет в него вшит. Кто-нибудь может рассказать подробности? Источник.

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