Итак, я просматривал некоторые статьи о создании 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. Мы можем легко сериализовать / десериализовать через json_encode()
и json_decode()
PHP и делать все, что захотим, с json_decode()
данными, не имея дело с различными методами HTTP-запросов.
Я что-то упускаю?
ОБНОВЛЕНИЕ 1:
Хорошо – после того, как вы пробрались через различные API и много узнали о XML-RPC , JSON-RPC , SOAP , REST, я пришел к выводу, что этот тип API звучит. Фактически, обмен стеками в значительной степени использует этот подход на своих сайтах, и я думаю, что эти люди знают, что они делают с помощью API-интерфейса Stack Exchange .
Идея 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 для структуры базы данных).
Теперь нам нужно перейти к проблеме идемпотенции . Обычно 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
.
Это вопрос безопасности и ремонтопригодности.
По возможности вы должны использовать «безопасные» (однонаправленные) методы, такие как GET и HEAD, чтобы ограничить потенциальную уязвимость.
По возможности вы должны использовать методы «идемпотент», такие как GET, HEAD, PUT и DELETE, которые не могут иметь побочные эффекты и, следовательно, менее подвержены ошибкам / легче контролировать.
Источник
Короче говоря, REST подчеркивает существительные над глаголами. По мере того, как ваш API становится более сложным, вы добавляете больше вещей, а не больше команд.
Вы спросили :
было бы проще просто принять объект JSON через обычный $ _POST, а затем ответить также в JSON
Из Википедии в REST :
Приложения RESTful максимизируют использование уже существующего, четко определенного интерфейса и других встроенных возможностей, предоставляемых выбранным сетевым протоколом, и минимизируют добавление новых функций приложения поверх него
Из того, что (мало) я видел, я считаю, что это обычно достигается за счет максимального использования существующих HTTP-глаголов и разработки схемы URL-адресов для вашей службы, которая настолько же мощна и самоочевидна, насколько это возможно.
Пользовательские протоколы данных (даже если они построены поверх стандартных, например SOAP или JSON) обескуражены и должны быть сведены к минимуму, чтобы наилучшим образом соответствовать идее REST.
SOAP RPC через HTTP, с другой стороны, побуждает каждого дизайнера приложений определять новый и произвольный словарный запас существительных и глаголов (например, getUsers (), savePurchaseOrder (…)), обычно наложенных на HTTP-адрес POST. Это игнорирует многие существующие возможности HTTP, такие как аутентификация, кэширование и согласование типов контента, и может оставить конструктора приложений повторно изобретать многие из этих функций в новом словаре.
Фактические объекты, с которыми вы работаете, могут быть в любом формате. Идея состоит в том, чтобы повторно использовать как можно больше HTTP, чтобы выявить ваши действия, которые пользователь хочет выполнить на этом ресурсе (запросы, управление / мутация, удаление).
Вы спросили :
Я что-то упускаю?
Намного больше узнать о REST и синтаксисе URI / HTTP-глаголах. Например, некоторые из глаголов являются идемпотентными, другие – нет. Я ничего не видел об этом в вашем вопросе, поэтому я не стал пытаться погрузиться в него. В других ответах и в Википедии есть много хорошей информации.
Кроме того, есть много, чтобы узнать о различных сетевых технологиях, построенных поверх HTTP, которые вы можете использовать, если используете действительно успокаивающий API. Я бы начал с проверки подлинности.
Что касается использования расширения для определения типа данных. Я заметил, что 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
Я что-то упускаю?
Да. 😉
Это явление существует из-за равномерного ограничения интерфейса . REST любит использовать уже существующие стандарты, а не изобретать колесо. Стандарт HTTP уже доказал свою высокую масштабируемость (сеть работает некоторое время). Почему мы должны исправить что-то, что не сломалось ?!
note Примечание. Единое ограничение интерфейса важно, если вы хотите отделить клиентов от службы. Он похож на определение интерфейсов для классов, чтобы отделить их друг от друга. Ofc. здесь унифицированный интерфейс состоит из таких стандартов, как HTTP , MIME-типы , URI , RDF , связанные словари данных , гидра vocab и т. д.
Хорошая семантика важна для программирования.
Использование дополнительных методов, кроме GET / POST, будет полезно, потому что это повысит читаемость вашего кода и упростит его поддержку.
Зачем?
Поскольку вы знаете, что GET будет извлекать данные из вашего api. Вы знаете, что POST добавит новые данные в вашу систему. Вы знаете, что PUT сделает обновления. DELETE удалит строки и т. Д. И т. Д.
Я обычно структурирую свои RESTFUL Web Services, так что у меня есть функция обратного вызова функции с именем то же, что и метод.
Я использую PHP, поэтому я использую function_exists (я думаю, его вызвал). Если функция не существует, я бросаю 405 (МЕТОД НЕ ДОПУСКАЕТСЯ).