Понимание REST: глаголы, коды ошибок и аутентификация

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

я осмотрелся и нашел несколько каркасов "скелета". В дополнение к ответам на мой вопрос, есть тоник, 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

как бы я выразил действия, такие как те, в архитектуре url RESTful?

моим инстинктом было бы сделать вызов GET по URL-адресу, как

/api/users/1/activate_login 

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

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

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

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

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

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

10 ответов


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


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

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


общаясь с коллекция URI нравится:http://example.com/resources/

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

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

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

  • удалить: значение, определенное как "удалить всю коллекцию".


при общении с URI нравится:http://example.com/resources/7HOU57Y

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

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

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

  • удалить: удалить имя члена коллекция.


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

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

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

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

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

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

например, запрос GET никогда не должен создавать сеанс в базе данных, возвращать cookie с новым идентификатором сеанса или оставлять какие-либо остатки на сервер. Команда get-это как Select в СУБД. Помните, что ответ на любой запрос с помощью команды GET должен быть кэшируемым при запросе с теми же параметрами, что и при запросе статической веб-страницы.


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

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

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

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


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

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

затем вы спросите свой сервер RESTful: "можете ли вы получить мне ресурс для этого идентификатора сеанса?".

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


проще говоря, вы делаете это совершенно отсталые.

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

цитата Рой Филдинг

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

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

честно говоря, многие видят кучу URI, а некоторые получают и ставят и сообщения и думают, что отдых легко. Отдыхать нелегко. RPC через HTTP легко, перемещение blobs данных взад и вперед проксированных через HTTP полезных нагрузок легко. Отдых, однако, выходит за рамки этого. Отдых-это протокол агностика. HTTP просто очень популярен и подходит для систем REST.

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

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

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

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

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

частью процесса проектирования системы 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 с именем " пользователи "и тип носителя"application/xml+youruser".

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

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

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

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

вынос здесь, однако, сами Ури в основном неважны. Приложение управляет 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"/>

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


re 1: пока это выглядит нормально. Не забудьте вернуть URI вновь созданного пользователя в заголовке " Location: "как часть ответа на сообщение вместе с кодом состояния" 201 Created".

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

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

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


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

2. вместо того, чтобы пытаться расширить HTTP с большим количеством глаголов, рассмотрите, что ваши предлагаемые глаголы могут быть сведены к основным методам и ресурсам HTTP. Например, вместо activate_login глагол, вы можете настроить такие ресурсы, как:/api/users/1/login/active который является простым логическим. Чтобы активировать логин, просто PUT документ, в котором говорится 'true' или 1 или любой другой. Для деактивации PUT документ там, который пуст или говорит 0 или false.

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

всякий раз, когда вам нужно добавить что-то (например, кредит) думать в терминах POSTs. Например, вы можете сделать 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, если это проще для вас.


основы остальное

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

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

  • HTTP 1.1
    • определения метода
    • статус определения кода
    • заголовки управления кэшем
    • принять и заголовки типа контента
    • заголовки auth
  • Мико (кодировке utf8 URI)
  • тело (выберите один)
    • зарегистрированный тип MIME конкретного приложения, например лабиринт + xml
    • конкретный тип MIME поставщика, например vnd.github+json
    • общий тип MIME с
      • применение конкретного RDF vocab, например ld+json & гидра, schema.org
      • профиль конкретного приложения, например hal+json & профиль ссылка param (я думаю)
  • ссылки
    • что должен содержать их (Выберите один)
      • отправка заголовки ссылке
      • отправка ответа гипермедиа, например html, atom + xml, hal+json, ld+json&hydra и т. д...
    • семантика
      • используйте IANA link relations и, вероятно, пользовательские отношения ссылок
      • Используйте конкретное приложение RDF vocab

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

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

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

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

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

    это довольно просто, почему мы используем хороший Ирис, как /users/123/password; гораздо легче написать логику маршрутизации на сервере, когда вы поймите ИРИ, просто прочитав его.

  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.

обзоры литература


для примеров, которые вы указали, я бы использовал следующее:

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.


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

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

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

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


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

9.3 GET

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

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

семантика метода GET изменяется на" частичный GET", если сообщение запроса содержит поле заголовка диапазона. Частичный GET запрашивает передачу только части сущности, как описано в разделе 14.35. Метод partial GET предназначен для уменьшения ненужного использования сети, позволяя частично извлеченным сущностям быть завершенными без передачи данных, уже удерживаемых клиент.

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

см. раздел 15.1.3 для соображений безопасности, при использовании для формы.

9.5 в должности

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

  - 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, определяется сервером и обычно зависит от запроса-URI. Размещенный объект подчинен этому URI точно так же, как файл подчинен каталогу, содержащему его, новостная статья подчинена Группе новостей, в которую она размещена, или запись подчинена базе данных.

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

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

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

запросы POST должны соответствовать требованиям передачи сообщений, изложенным в разделе 8.2.

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

9.6 поставить

метод PUT запрашивает, что вложенные сущности храниться под поставленный запрос URI. Если URI-запрос ссылается на уже существующий ресурс, вложенный объект следует рассматривать как измененную версию ресурса, находящегося на исходном сервере. Если URI-запрос не указывает на существующий ресурс, и этот URI может быть определен как новый ресурс запрашивающим агентом пользователя, исходный сервер может создать ресурс с этим URI. При создании нового ресурса исходный сервер должен сообщить агент пользователя через 201 (созданный) ответ. Если существующий ресурс изменен, необходимо отправить 200 (OK) или 204 (без содержимого) кода ответа, чтобы указать на успешное выполнение запроса. Если ресурс не может быть создан или изменен с помощью Request-URI, необходимо дать соответствующий ответ на ошибку, отражающий характер проблемы. Получатель сущности не должен игнорировать заголовки Content-* (например, Content-Range), которые он не понимает или не реализует и должен возвращает 501 (не реализованный) ответ в таких случаях.

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

фундаментальное различие между запросами POST и PUT отражается в различном значении 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 запрашивает, чтобы исходный сервер удалил ресурс, идентифицированный запросом-URI. Этот метод может быть переопределен вмешательством человека (или другим значит) на исходном сервере. Клиенту нельзя гарантировать, что операция выполнена, даже если код состояния, возвращенный с исходного сервера, указывает, что действие выполнено успешно. Однако сервер не должен указывать на успех, если в момент получения ответа он не намерен удалить ресурс или переместить его в недоступное место.

успешный ответ должен быть 200 (OK), если ответ включает объект, описывающий состояние, 202 (принято), если действие еще не было принято, или 204 (без содержания), если действие было принято, но ответ не включает субъект.

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


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

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

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

например, возврат "404 не найден" при вызове /users / путают, потому что это может означать:

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

"403 запрещено Доступ запрещен" может означать:

  • требуется специальное разрешение. Браузеры могут справиться с этим, спросив пользователя/пароль. (HTTP)
  • неправильные права доступа настроено на сервере. (HTTP)
  • вы должны быть аутентифицированы (REST)

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

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

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

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

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

С Wiki:

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