REST API - зачем использовать PUT DELETE POST GET?

130

Итак, я просматривал некоторые статьи о создании REST API. Некоторые из них предлагают использовать все типы HTTP-запросов: например PUT DELETE POST GET. Мы будем создавать, например, index.php и писать API следующим образом:

$method = $_SERVER['REQUEST_METHOD'];
$request = split("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    ....some put action.... 
    break;
  case 'POST':
    ....some post action.... 
    break;
  case 'GET':
    ....some get action.... 
    break;
  case 'DELETE':
    ....some delete action.... 
    break;
}

ОК, предоставлено - я мало что знаю о веб-сервисах (пока). Но было бы проще просто принять объект JSON через регулярные POST или GET (которые будут содержать имя метода и все параметры), а затем отвечать и в JSON. Мы можем легко сериализовать /deserialize через PHP json_encode() и json_decode() и делать все, что захотим, с этими данными, не имея дело с различными методами HTTP-запроса.

Я что-то пропустил?

ОБНОВЛЕНИЕ 1:

Хорошо - после перекодировки через различные API и многого узнать о XML-RPC, JSON-RPC, SOAP, REST Я пришел к выводу, что этот тип API звучит. Фактически, обмен стеками в значительной степени использует этот подход на своих сайтах, и я действительно думаю, что эти люди знают, что они делают API-интерфейс стека.

  • 4
    Зачем использовать JSON? Что делать, если нет JSON, а это обычный GET?
  • 1
    Да. w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
Теги:
rest
soap

7 ответов

176
Лучший ответ

Идея RE presentational S tate T ransfer заключается не в доступе к данным самым простым способом.

Вы предложили использовать пост-запросы для доступа к JSON, что является совершенно допустимым способом доступа/обработки данных.

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

Например:

GET: /cars/make/chevrolet

скорее всего, вернет список автомобилей Chevy. Хороший REST api может даже включать некоторые параметры вывода в querystring, например ?output=json или ?output=html, что позволит аксессуар решить, в каком формате должна быть закодирована информация.

После небольшого размышления о том, как разумно включить ввод данных в REST API, я пришел к выводу, что лучший способ указать тип данных явно будет через уже существующее расширение файла, такое как .js, .json, .html или .xml. Недопустимое расширение файла по умолчанию будет иметь значение по умолчанию (например, JSON); расширение, которое не поддерживается, может вернуть 501 Not Implemented код состояния.

Другой пример:

POST: /cars/
{ make:chevrolet, model:malibu, colors:[red, green, blue, grey] }

вероятно, собирается создать новый chevy malibu в db с соответствующими цветами. Я говорю скорее всего, поскольку REST api не обязательно должен быть напрямую связан с структурой базы данных. Это всего лишь интерфейс маскировки, так что истинные данные защищены (подумайте об этом как о accessor и mutators для структуры базы данных).

Теперь нам нужно перейти на вопрос idempotence. Обычно REST реализует CRUD через HTTP. HTTP использует GET, PUT, POST и DELETE для запросов.

Очень упрощенная реализация REST может использовать следующее отображение CRUD:

Create -> Post
Read   -> Get
Update -> Put
Delete -> Delete

Существует проблема с этой реализацией: Post определяется как метод без idempotent. Это означает, что последующие вызовы одного и того же метода Post приведут к состояниям разных серверов. Get, Put и Delete, являются идемпотентными; что означает, что вызов их несколько раз должен приводить к идентичному состоянию сервера.

Это означает, что запрос, например:

Delete: /cars/oldest

может быть реализована как:

Post: /cars/oldest?action=delete

В то время как

Delete: /cars/id/123456

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

Лучшим способом обработки удаления элемента oldest будет запрос:

Get: /cars/oldest

и используйте ID из полученных данных, чтобы сделать запрос DELETE:

Delete: /cars/id/[oldest id]

Проблема с этим методом будет связана с добавлением другого элемента /cars между запросами /oldest и выпуском DELETE.

  • 0
    Спасибо за хорошее объяснение. Но как идемпотентность помогает нам в веб-разработке? почему мы должны заботиться об этом? возможно кеширование?
  • 3
    @ И это сочетание нескольких причин: следование рекомендациям HTTP означает, что у вас (вероятно) будет меньше проблем с обратной совместимостью, когда что-то изменится; использование html-формы через POST предупредит пользователя о множественных отправках одних и тех же данных (это предотвратит неидемпотентную транзакцию); следование четко определенной передовой практике - это, пожалуй, лучшая практика. Отдых не определен с конкретной реализацией, что позволяет вам использовать его по своему усмотрению. Я бы предложил воспользоваться всеми кодами ошибок HTTP и методами запроса, но вы можете делать это так, как хотите
Показать ещё 17 комментариев
37

Это вопрос безопасности и поддержки.

безопасные методы

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

idempotent методы

По возможности вы должны использовать методы "идемпотент", такие как GET, HEAD, PUT и DELETE, которые не могут иметь побочные эффекты и, следовательно, менее подвержены ошибкам/легче контролировать.

Источник

  • 1
    Извините, но как работают PUT и DELETE идемпотентные методы? Они влияют на состояние сервера и его данных!
  • 27
    @Computer: выполнение того же самого PUT или того же самого DELETE приводит к тому же конечному состоянию. Вот что значит «идемпотент».
Показать ещё 4 комментария
22

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

  • 1
    Мне действительно нравится, как краткое это объяснение. Спасибо @Neil!
  • 2
    У меня была небольшая проблема с тем, чтобы обдумать это. Этот пост ( lornajane.net/posts/2013/… ) о том, что глагол должен исходить из HTTP-запроса, так что URI должен содержать только существительные, прояснил его немного для меня
9

Вы спросили:

было бы проще просто принять объект JSON через обычный $_POST, а затем ответить также в JSON

Из Википедии на REST:

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

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

Пользовательские протоколы данных (даже если они построены поверх стандартных, например SOAP или JSON) обескуражены и должны быть сведены к минимуму, чтобы наилучшим образом соответствовать идее REST.

SOAP RPC через HTTP, с другой стороны, побуждает каждого дизайнера приложений определять новый и произвольный словарный запас существительных и глаголов (например, getUsers(), savePurchaseOrder (...)), обычно наложенных на HTTP-сообщение POST 'глагол. Это игнорирует многие существующие HTTP-возможности, такие как аутентификация, кэширование и согласование типов контента, и может оставить конструктора приложений повторно изобретать многие из этих функций в новом словаре.

Фактические объекты, с которыми вы работаете, могут быть в любом формате. Идея состоит в том, чтобы повторно использовать как можно больше HTTP, чтобы выявить ваши действия, которые пользователь хочет выполнить на этом ресурсе (запросы, управление/мутация, удаление).

Вы спросили:

Я что-то пропустил?

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

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

8

В отношении использования расширения для определения типа данных. Я заметил, что API MailChimp делает это, но я не думаю, что это хорошая идея.

GET /zzz/cars.json/1

GET /zzz/cars.xml/1

Мой звук похож на хорошую идею, но я думаю, что "более старый" подход лучше - с использованием HTTP-заголовков

GET /xxx/cars/1
Accept: application/json

Также HTTP-заголовки намного лучше подходят для передачи данных по перекрестным данным (если когда-либо кому-то это понадобится)

POST /zzz/cars
Content-Type: application/xml     <--- indicates we sent XML to server
Accept: application/json          <--- indicates we want get data back in JSON format  
4

Я что-то пропустил?

Да.; -)

Это явление существует из-за равномерного ограничения интерфейса. REST любит использовать уже существующие стандарты, а не изобретать колесо. Стандарт HTTP уже доказал свою высокую масштабируемость (сеть работает некоторое время). Почему мы должны исправить что-то, что не нарушено?!

Примечание: равномерное ограничение интерфейса важно, если вы хотите отделить клиентов от службы. Он похож на определение интерфейсов для классов, чтобы отделить их друг от друга. Ofc. здесь равномерный интерфейс состоит из таких стандартов, как HTTP, MIME types, URI, RDF, связанные словари данных, hydra vocab и т.д.

0

Хорошая семантика важна в программировании.

Использование большего количества методов, кроме GET/POST, будет полезно, потому что это повысит читаемость вашего кода и упростит его поддержку.

Почему?

Поскольку вы знаете, что GET будет извлекать данные из вашего api. Вы знаете, что POST добавит новые данные в вашу систему. Вы знаете, что PUT сделает обновления. DELETE удалит строки и т.д., И т.д.,

Я обычно структурирую свои RESTFUL Web Services, так что у меня есть функция обратного вызова функции с именем того же самого метода, что и метод.

Я использую PHP, поэтому я использую function_exists (я думаю, его вызвал). Если функция не существует, я бросаю 405 (МЕТОД НЕ ДОПУСКАЕТСЯ).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню