Понимание REST: глаголы, коды ошибок и аутентификация - PullRequest
586 голосов
/ 04 января 2010

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

Я осмотрелся и нашел несколько "каркасных" рамок. В дополнение к ответам на мой вопрос есть Tonic , REST Framework, который мне нравится, потому что он очень легкий.

Мне нравится REST лучше всего за его простоту, и я хотел бы создать архитектуру API на его основе. Я пытаюсь разобраться с основными принципами и еще не до конца понял. Поэтому ряд вопросов.

1. Я правильно понимаю?

Допустим, у меня есть ресурс "пользователи". Я мог бы настроить несколько URI, например, так:

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

Является ли это правильным представлением архитектуры RESTful на данный момент?

2. Мне нужно больше глаголов

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

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

activate_login
deactivate_login
change_password
add_credit

как бы я выразил действия, подобные действиям в архитектуре RESTful URL?

Мой инстинкт: GET-вызов URL-адреса, например

/api/users/1/activate_login 

и ожидайте код статуса обратно.

Однако это отличается от идеи использования HTTP-глаголов. Что ты думаешь?

3. Как вернуть сообщения об ошибках и коды

Большая часть красоты REST связана с использованием стандартных методов HTTP. При ошибке я выдаю заголовок с кодом ошибки 3xx, 4xx или 5xx. Для подробного описания ошибки я могу использовать тело (правильно?). Все идет нормально. Но как можно было бы передать собственный код ошибки , который более подробно описывает неполадку (например, «не удалось подключиться к базе данных» или «неверный вход в базу данных»)? Если я добавлю его в тело вместе с сообщением, мне придется потом разобрать его. Есть ли стандартный заголовок для такого рода вещей?

4. Как сделать аутентификацию

  • Как будет выглядеть аутентификация на основе ключа API в соответствии с принципами REST?
  • Есть ли сильные стороны против использования сессий при аутентификации клиента REST, кроме того, что это явное нарушение принципа REST? :) (шутка здесь только наполовину, аутентификация на основе сеанса хорошо подойдет для моей существующей инфраструктуры.)

Ответы [ 10 ]

605 голосов
/ 07 января 2010

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


Пункт 1: Я правильно понимаю?

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


При работе с Коллекция URI, например: http://example.com/resources/

  • GET : список членов коллекции с указанием их URI для дальнейшей навигации. Например, перечислите все автомобили на продажу.

  • PUT : Значение, определенное как «заменить всю коллекцию другой коллекцией».

  • POST : создание новой записи в коллекции, в которой идентификатор автоматически присваивается коллекцией. Созданный идентификатор обычно включается как часть данных, возвращаемых этой операцией.

  • УДАЛИТЬ : Значение, определенное как «удалить всю коллекцию».


При работе с членом URI, например: http://example.com/resources/7HOU57Y

  • GET : получение представления адресуемого члена коллекции, выраженного в соответствующем типе MIME.

  • PUT : обновить адресуемый элемент коллекции или создать его с указанным идентификатором.

  • POST : Рассматривает адресуемый элемент как отдельную коллекцию и создает нового подчиненного.

  • УДАЛИТЬ : Удалить указанного члена коллекции.


Точка 2: мне нужно больше глаголов

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

Активировать / деактивировать логин : Если вы создаете новый сеанс, то вы можете рассмотреть «сеанс» как ресурс. Чтобы создать новый сеанс, используйте POST для http://example.com/sessions/ с учетными данными в теле. Чтобы истечь, используйте PUT или DELETE (возможно, в зависимости от того, намереваетесь ли вы сохранить историю сеанса) до http://example.com/sessions/SESSION_ID.

Изменить пароль: На этот раз ресурс «пользователь». Вам потребуется PUT на http://example.com/users/USER_ID со старыми и новыми паролями в теле. Вы действуете на «пользовательском» ресурсе, а изменение пароля - это просто запрос на обновление. Это очень похоже на оператор UPDATE в реляционной базе данных.

Мой инстинкт был бы сделать вызов GET на URL, как /api/users/1/activate_login

Это противоречит основному принципу REST: правильному использованию HTTP-глаголов. Любой запрос GET никогда не должен оставлять никаких побочных эффектов.

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


Пункт 3: Как вернуть сообщения об ошибках и коды

Рассматривать коды состояния HTTP 4xx или 5xx как категории ошибок. Вы можете уточнить ошибку в теле.

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

Другой категорией ошибок будет семейство 4xx, которое в целом указывает на то, что клиент сделал что-то не так. В частности, эта категория ошибок обычно указывает клиенту, что нет необходимости повторять запрос, как он есть, потому что он будет постоянно сбой. т.е. клиент должен что-то изменить, прежде чем повторить этот запрос. Например, ошибки «Ресурс не найден» (HTTP 404) или «Неверный запрос» (HTTP 400) попадают в эту категорию.


Пункт 4: Как выполнить аутентификацию

Как указано в пункте 1, вместо аутентификации пользователя вы можете подумать о создании сеанса. Вам будет возвращен новый «ID сеанса» вместе с соответствующим кодом состояния HTTP (200: доступ разрешен или 403: доступ запрещен).

Затем вы спросите свой сервер RESTful: «Вы можете ПОЛУЧИТЬ мне ресурс для этого идентификатора сеанса?».

Режим аутентификации отсутствует - REST не имеет состояния: вы создаете сеанс, просите сервер предоставить вам ресурсы, используя этот идентификатор сеанса в качестве параметра, и при выходе из системы вы удаляете или истекаете сеанс.

77 голосов
/ 08 января 2010

Проще говоря, вы делаете это полностью назад.

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

Цитировать Рой Филдинг

API REST должен тратить почти все его описательные усилия в определении тип (ы) медиа, используемые для представления ресурсы и вождение приложения состояние, или в определении расширенного имена отношений и / или разметка с поддержкой гипертекста для существующих стандартные типы носителей. Любое затраченное усилие описывая какие методы использовать на каких Интересующие URI должны быть полностью определены в рамках правила обработки для типа носителя (и, в большинстве случаев, уже определены по существующим типам носителей). [Отказ здесь подразумевается, что вне группы информация стимулирует взаимодействие вместо гипертекста.]

Люди всегда начинают с URI и думают, что это решение, а затем им не хватает ключевого понятия в архитектуре REST, а именно, как указано выше: «Ошибка здесь подразумевает, что внеполосная информация стимулирует взаимодействие вместо гипертекста. "

Если честно, многие видят кучу URI, а также некоторые GET, PUT и POST и думают, что REST - это просто. ОТДЫХ не легко. RPC через HTTP - это просто, перемещение больших объемов данных назад и вперед по прокси через полезные нагрузки HTTP очень просто. Отдых, однако, выходит за рамки этого. REST не зависит от протокола. HTTP просто очень популярен и подходит для систем REST.

REST относится к типам носителей, их определениям и тому, как приложение управляет действиями, доступными этим ресурсам через гипертекст (ссылки, эффективно).

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

Мне кажется, что оба подхода имеют свое место: XHTML очень хорошо работает в сценариях, которые перекрывают как управляемую человеком, так и управляемую машиной сеть, тогда как более ранние, более конкретные типы данных, которые я чувствую, лучше облегчают взаимодействие между машинами. Я считаю, что подъем товарных форматов может сделать переговоры о контенте потенциально трудными. «application / xml + yourresource» гораздо более специфичен как тип носителя, чем «application / xhtml + xml», поскольку последний может применяться ко многим полезным нагрузкам, которые могут или не могут быть чем-то, что на самом деле интересует клиент машины, и не может определить без самоанализа.

Однако XHTML очень хорошо работает (очевидно) в человеческой сети, где веб-браузеры и рендеринг очень важны.

Ваше приложение поможет вам в принятии таких решений.

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

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

Например, у вас может быть:

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

Ваша документация расскажет о поле rel, названном «users», и типе носителя «application / xml + youruser».

Эти ссылки могут показаться излишними, все они в основном используют один и тот же URI. Но это не так.

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

Если вы отправите POST по этому URL, вам нужно будет передать документ «application / xml + usercollection», который, вероятно, будет содержать только один экземпляр пользователя в документе, чтобы вы могли добавить пользователя или нет, возможно, к добавить несколько сразу. Возможно, ваша документация предполагает, что вы можете просто передать один тип пользователя вместо коллекции.

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

Однако здесь следует отметить, что сами URI в принципе не важны. Приложение контролирует URI, а не клиентов. Помимо нескольких «точек входа», ваши клиенты должны полагаться на URI, предоставленные приложением для его работы.

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

Эти две ссылки семантически идентичны в глазах клиентов:

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

Итак, сосредоточьтесь на своих ресурсах. Сосредоточьтесь на их переходах состояний в приложении и на том, как это лучше всего достигается.

30 голосов
/ 04 января 2010

re 1 : Пока все выглядит хорошо. Не забудьте вернуть URI вновь созданного пользователя в заголовке «Location:» как часть ответа на POST вместе с кодом состояния «201 Created».

re 2 : Активация через GET - плохая идея, и включение глагола в URI - запах дизайна. Вы можете рассмотреть вопрос о возвращении формы на GET. В веб-приложении это будет HTML-форма с кнопкой отправки; в случае использования API вы можете вернуть представление, содержащее URI для PUT, чтобы активировать учетную запись. Конечно, вы также можете включить этот URI в ответ на POST для / users. Использование PUT гарантирует, что ваш запрос идемпотентен, то есть его можно безопасно отправить снова, если клиент не уверен в успехе. В общем, подумайте о том, в какие ресурсы вы можете превратить свои глаголы (своего рода «обозначение глаголов»). Спросите себя, с каким методом ваши конкретные действия наиболее тесно связаны. Например. change_password -> PUT; деактивировать -> возможно УДАЛИТЬ; add_credit -> возможно POST или PUT. Укажите клиенту соответствующие URI, включив их в свои представления.

re 3. Не изобретайте новые коды статуса, если только вы не уверены, что они настолько универсальны, что заслуживают стандартизации во всем мире. Старайтесь использовать наиболее подходящий код состояния (читайте обо всех из них в RFC 2616). Включите дополнительную информацию в тело ответа. Если вы действительно уверены, что хотите изобрести новый код состояния, подумайте еще раз; если вы все еще верите в это, убедитесь, что вы выбрали хотя бы правильную категорию (1xx -> OK, 2xx -> информационное, 3xx -> перенаправление; 4xx-> ошибка клиента, 5xx -> ошибка сервера). Я упоминал, что изобретать новые коды состояния - плохая идея?

re 4. Если возможно, используйте встроенную в HTTP структуру аутентификации. Проверьте, как Google выполняет аутентификацию в GData. В общем, не помещайте ключи API в ваши URI. Старайтесь избегать сеансов для повышения масштабируемости и поддержки кэширования - если ответ на запрос отличается из-за чего-то, что произошло раньше, вы обычно привязываете себя к конкретному экземпляру процесса сервера. Гораздо лучше превратить состояние сеанса либо в состояние клиента (например, сделать его частью последующих запросов), либо сделать его явным, превратив его в (ресурсное) состояние ресурса, то есть присвоить ему собственный URI.

22 голосов
/ 05 января 2010

1. У вас есть правильное представление о том, как проектировать свои ресурсы, ИМХО. Я бы ничего не изменил.

2. Вместо того, чтобы пытаться расширить HTTP с помощью большего числа глаголов, рассмотрите, к чему могут быть сокращены ваши предложенные глаголы, с точки зрения основных методов и ресурсов HTTP. Например, вместо глагола activate_login вы можете настроить такие ресурсы, как: /api/users/1/login/active, который является простым логическим значением. Чтобы активировать логин, просто PUT документ там, который говорит «true» или 1 или что-то еще. Чтобы деактивировать, PUT документ там, который пустой или говорит 0 или ложь.

Аналогично, чтобы изменить или установить пароли, просто наберите от PUT s до /api/users/1/password.

Всякий раз, когда вам нужно что-то добавить (например, кредит), думайте с точки зрения POST с. Например, вы можете сделать POST для ресурса, подобного /api/users/1/credits, с телом, содержащим количество добавляемых кредитов. PUT на том же ресурсе можно использовать для перезаписи значения, а не для добавления. POST с отрицательным числом в теле вычтет и т. Д.

3. Я бы настоятельно рекомендовал не расширять базовые коды состояния HTTP. Если вы не можете найти тот, который точно соответствует вашей ситуации, выберите ближайший и поместите детали ошибки в теле ответа. Также помните, что HTTP-заголовки являются расширяемыми; Ваше приложение может определить все пользовательские заголовки, которые вам нравятся. Например, одно приложение, над которым я работал, могло возвращать 404 Not Found при нескольких обстоятельствах. Вместо того, чтобы заставлять клиента анализировать тело ответа по этой причине, мы просто добавили новый заголовок X-Status-Extended, который содержал наши собственные расширения кода состояния. Таким образом, вы можете увидеть ответ вроде:

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

Таким образом, HTTP-клиент, такой как веб-браузер, по-прежнему будет знать, что делать с обычным кодом 404, а более сложный HTTP-клиент может посмотреть в заголовке X-Status-Extended более подробную информацию.

4. Для аутентификации я рекомендую использовать HTTP-аутентификацию, если вы можете. Но IMHO, нет ничего плохого в использовании аутентификации на основе файлов cookie, если это проще для вас.

12 голосов
/ 18 сентября 2014

Основы ОТДЫХА

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

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

  • HTTP 1.1
    • определения методов
    • определения кодов состояния
    • заголовки управления кешем
    • принять и заголовки типа содержимого
    • заголовки аутентификации
  • IRI (utf8 URI )
  • тело (выберите одно)
    • зарегистрированный тип приложения MIME, например лабиринт + XML
    • тип MIME, определяемый поставщиком, например, vnd.github + * 1037 JSON *
    • универсальный тип MIME с
      • специфичный для приложения словарь RDF, например, ld + json & гидра , schema.org
      • профиль приложения, например hal + json и параметр ссылки на профиль (по-моему)
  • гиперссылок
    • что должно их содержать (выберите одно)
      • отправка заголовков ссылок
      • отправка гипермедиа ответа, например, html, atom + xml, hal + json, ld + json & hydra и т. д. ...
    • семантика
      • использовать отношения ссылок IANA и, возможно, пользовательские отношения ссылок
      • использовать специфический для приложения RDF vocab

REST имеет ограничение без сохранения состояния, которое объявляет, что связь между службой REST и клиентом должна быть без сохранения состояния. Это означает, что служба REST не может поддерживать состояния клиента, поэтому у вас не может быть хранилища сеансов на стороне сервера. Вы должны аутентифицировать каждый запрос. Так, например, базовая аутентификация HTTP (часть стандарта HTTP) приемлема, поскольку она отправляет имя пользователя и пароль при каждом запросе.

Чтобы ответить на ваши вопросы

  1. Да, это может быть.

    Просто отметим, что клиенты не заботятся о структуре IRI, они заботятся о семантике, потому что они следуют по ссылкам, имеющим атрибуты отношений ссылок или связанных данных (RDF).

    Единственное, что важно в IRI, это то, что один IRI должен идентифицировать только один ресурс. Разрешено одному ресурсу, как пользователю, иметь много разных IRI.

    Довольно просто, почему мы используем хорошие IRI, такие как /users/123/password; гораздо проще написать логику маршрутизации на сервере, когда вы понимаете IRI, просто читая его.

  2. У вас есть больше глаголов, таких как PUT, PATCH, OPTIONS и даже больше, но вам не нужно больше их ... Вместо того, чтобы добавлять новые глаголы, вы должны научиться добавлять новые ресурсы.

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (Вход в систему не имеет смысла с точки зрения REST из-за ограничения без сохранения состояния.)

  3. Вашим пользователям все равно, почему проблема существует. Они хотят знать только, есть ли успех или ошибка, и, возможно, сообщение об ошибке, которое они могут понять, например: «Извините, но мы не смогли сохранить ваше сообщение.» И т. Д. *

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

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

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

Связанная литература

11 голосов
/ 04 января 2010

В приведенных вами примерах я бы использовал следующее:

activate_login

POST /users/1/activation

deactivate_login

DELETE /users/1/activation

change_password

PUT /passwords (предполагается, что пользователь прошел аутентификацию)

add_credit

POST /credits (предполагается, что пользователь прошел аутентификацию)

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

DELETE /users/1.xml

Вы отправили бы ответ обратно в XML, то же самое было бы верно для JSON и т. Д. *

Для аутентификации вы должны использовать http аутентификацию.

6 голосов
/ 04 января 2010
  1. Используйте сообщение, когда вы не знаете, как будет выглядеть новый URI ресурса (вы создаете нового пользователя, приложение назначит новому пользователю его идентификатор), PUT для обновления или создания ресурсов, которые, как вы знаете, будут представлен (пример: PUT /myfiles/thisismynewfile.txt)
  2. вернуть описание ошибки в теле сообщения
  3. Вы можете использовать HTTP-аутентификацию (если этого достаточно) Веб-сервисы должны быть государственными
5 голосов
/ 04 января 2010

Подробно, но скопировано из спецификации метода HTTP 1.1 в http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

9,3 GET

Метод GET означает получение любой информации (в форме объекта), идентифицируемой Request-URI. Если Request-URI относится к процессу создания данных, то именно полученные данные должны быть возвращены в качестве объекта в ответе, а не как исходный текст процесса, если только этот текст не является выходом процесса.

Семантика метода GET изменяется на «условное GET», если сообщение запроса включает в себя поле заголовка If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match или If-Range , Условный метод GET запрашивает, чтобы объект передавался только при обстоятельствах, описанных в поле (ах) условного заголовка. Условный метод GET предназначен для уменьшения ненужного использования сети, позволяя обновлять кэшированные объекты, не требуя многократных запросов или передачи данных, уже удерживаемых клиентом.

Семантика метода GET изменяется на «частичное GET», если сообщение запроса включает поле заголовка Range. Частичное GET запрашивает, чтобы была передана только часть объекта, как описано в разделе 14.35. Метод частичного GET предназначен для уменьшения ненужного использования сети, позволяя завершать частично извлеченные объекты без передачи данных, уже сохраненных клиентом.

Ответ на запрос GET кэшируется тогда и только тогда, когда он соответствует требованиям для кэширования HTTP, описанным в разделе 13.

Сведения о безопасности при использовании форм см. В разделе 15.1.3.

9,5 POST

Метод POST используется для запроса, чтобы исходный сервер принял объект, заключенный в запросе, в качестве нового подчиненного ресурса, идентифицируемого Request-URI в строке запроса. POST разработан для того, чтобы единообразный метод мог выполнять следующие функции:

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

Фактическая функция, выполняемая методом POST, определяется сервером и обычно зависит от Request-URI. Размещаемая сущность подчиняется этому URI так же, как файл подчиняется каталогу, в котором он находится, новостная статья подчиняется группе новостей, в которой она размещена, или запись подчиняется базе данных.

Действие, выполняемое методом POST, может не привести к ресурсу, который может быть идентифицирован по URI. В этом случае либо 200 (ОК), либо 204 (Нет содержимого) - это соответствующий статус ответа, в зависимости от того, содержит ли ответ объект, описывающий результат.

Если ресурс был создан на исходном сервере, ответ ДОЛЖЕН быть 201 (Создан) и содержать объект, который описывает состояние запроса и ссылается на новый ресурс, и заголовок Location (см. Раздел 14.30).

Ответы на этот метод не могут быть кэшированы, если ответ не включает в себя соответствующие поля заголовка Cache-Control или Expires. Однако ответ 303 (см. «Другое») можно использовать для указания агенту пользователя на получение кэшируемого ресурса.

POST-запросы ДОЛЖНЫ соответствовать требованиям к передаче сообщений, изложенным в разделе 8.2.

См. Раздел 15.1.3 по соображениям безопасности.

9,6 PUT

Метод PUT запрашивает, чтобы вложенный объект был сохранен под предоставленным Request-URI. Если Request-URI ссылается на уже существующий ресурс, вложенный объект СЛЕДУЕТ рассматривать как модифицированную версию, находящуюся на исходном сервере. Если Request-URI не указывает на существующий ресурс, и этот URI может быть определен как новый ресурс запрашивающим пользовательским агентом, сервер происхождения может создать ресурс с этим URI. Если новый ресурс создан, сервер происхождения ДОЛЖЕН проинформировать пользовательский агент через ответ 201 (Создано). Если существующий ресурс изменен, то должны быть отправлены коды ответа 200 (ОК) или 204 (Нет содержимого), чтобы указать успешное завершение запроса. Если ресурс не может быть создан или изменен с помощью Request-URI, СЛЕДУЕТ дать соответствующий ответ об ошибке, отражающий природу проблемы. Получатель объекта НЕ ДОЛЖЕН игнорировать какие-либо заголовки Content- * (например, Content-Range), которые он не понимает или не реализует, и ДОЛЖЕН возвращать ответ 501 (Не реализовано) в таких случаях.

Если запрос проходит через кеш и Request-URI идентифицирует одну или несколько кешированных в данный момент сущностей, эти записи ДОЛЖНЫ рассматриваться как устаревшие. Ответы на этот метод не кэшируются.

Принципиальное различие между запросами POST и PUT отражается в различном значении Request-URI. URI в запросе POST идентифицирует ресурс, который будет обрабатывать вложенный объект. Этот ресурс может быть процессом приема данных, шлюзом к другому протоколу или отдельным объектом, принимающим аннотации. Напротив, URI в запросе PUT идентифицирует объект, заключенный в запросе - пользовательский агент знает, для чего предназначен URI, и сервер НЕ ДОЛЖЕН пытаться применить запрос к какому-либо другому ресурсу. Если сервер желает, чтобы запрос был применен к другому URI,

он ДОЛЖЕН послать ответ 301 (Постоянно перемещен); Пользовательский агент МОЖЕТ затем принять собственное решение относительно того, следует ли перенаправить запрос.

Один ресурс МОЖЕТ быть идентифицирован многими различными URI. Например, статья может иметь URI для идентификации «текущей версии», которая отделена от URI, идентифицирующего каждую конкретную версию. В этом случае запрос PUT для общего URI может привести к тому, что исходный сервер определит несколько других URI.

HTTP / 1.1 не определяет, как метод PUT влияет на состояние исходного сервера.

PUT-запросы ДОЛЖНЫ соответствовать требованиям к передаче сообщений, изложенным в разделе 8.2.

Если не указано иное для конкретного заголовка объекта, заголовки объекта в запросе PUT ДОЛЖНЫ применяться к ресурсу, созданному или измененному PUT.

9,7 УДАЛИТЬ

Метод DELETE запрашивает, чтобы исходный сервер удалил ресурс, указанный в Request-URI. Этот метод МОЖЕТ быть отменен вмешательством человека (или другими средствами) на исходном сервере. Клиент не может быть гарантирован, что операция была выполнена, даже если код состояния, возвращенный с исходного сервера, указывает, что действие было успешно выполнено. Однако серверу НЕ СЛЕДУЕТ указывать успех, если только во время ответа он не намерен удалить ресурс или переместить его в недоступное место.

Успешный ответ ДОЛЖЕН быть 200 (ОК), если ответ включает в себя объект, описывающий статус, 202 (Принят), если действие еще не было принято, или 204 (Нет содержимого), если действие было выполнено, но ответ не включает сущность.

Если запрос проходит через кеш, а Request-URI идентифицирует одну или несколько кешированных в данный момент сущностей, эти записи ДОЛЖНЫ рассматриваться как устаревшие. Ответы на этот метод не кэшируются.

5 голосов
/ 04 января 2010

Я бы предложил (в качестве первого прохода), что PUT должен использоваться только для обновления существующих объектов. POST следует использовать для создания новых. т.е.

/api/users     when called with PUT, creates user record

мне не подходит. Однако остальная часть вашего первого раздела (использование глагола) выглядит логично.

2 голосов
/ 23 сентября 2017

О кодах возврата REST: неправильно смешивать коды протокола HTTP и результаты REST.

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

HTTP-коды возврата связаны с самим HTTP Request. Вызов REST выполняется с использованием запроса протокола передачи гипертекста, и он работает на более низком уровне, чем сам вызванный метод REST. REST является концепцией / подходом, и его выводом является бизнес / логический результат, в то время как HTTP-код результата - транспорт один.

Например, возвращение «404 Не найдено», когда вы звоните / users /, вызывает замешательство, поскольку это может означать:

  • неверный URI (HTTP)
  • Пользователи не найдены (REST) ​​

«403 Запрещено / Доступ запрещен» может означать:

  • Требуется специальное разрешение. Браузеры могут справиться с этим, спросив пользователя / пароль. (HTTP)
  • Неправильные разрешения доступа настроены на сервере. (HTTP)
  • Вам необходимо пройти проверку подлинности (REST) ​​

И список может продолжаться с «500 Server error» (ошибка в HTTP-запросе Apache / Nginx или ошибка бизнес-ограничения в REST) ​​или другими ошибками HTTP и т. Д.

Из кода трудно понять, что являлось причиной сбоя, сбоя HTTP (транспорта) или сбоя REST (логического).

Если физический HTTP-запрос был успешно выполнен, он должен всегда возвращать 200 кодов, независимо от того, найдены записи или нет. Поскольку ресурс URI найден и обработан сервером http. Да, он может вернуть пустой набор. Можно ли получить пустую веб-страницу с 200 в качестве результата http, верно?

Вместо этого вы можете вернуть 200 HTTP-код и просто JSON с пустым массивом / объектом или использовать флаг результата / успеха bool для информирования о состоянии выполненной операции.

Кроме того, некоторые интернет-провайдеры могут перехватить ваши запросы и вернуть вам http-код 404. Это не означает, что ваши данные не найдены, но что-то не так на транспортном уровне.

С Wiki :

В июле 2004 года британский телекоммуникационный провайдер BT Group развернул Cleanfeed система блокировки контента, которая возвращает ошибку 404 на любой запрос Контент, который Интернет-часы считают незаконным Фонд. Другие интернет-провайдеры возвращают ошибку HTTP 403 «запрещенный» в том же обстоятельства. Практика использования поддельных ошибок 404 в качестве средства Скрытая цензура была также зарегистрирована в Таиланде и Тунисе. В Тунис, где цензура была жестокой до революции 2011 года, люди узнали о природе фальшивых 404 ошибок и создали воображаемый персонаж по имени "Аммар 404", который представляет "невидимое цензор».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...