Выход за рамки CRUD в службах RESTful

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

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

  • Для чтения и обновления свойств телевизора мы будем использовать следующий URI:

    http://domain/tv/ ПОЛУЧИТЬ | PUT - получение и обновление свойств телевизора. (company, owner, inches)

  • Для потребления видео мы будем использовать следующий URI:

    ws://domain/tv/video — (предполагается, что WebSocket — лучший вариант для передачи видеоконтента)

  • И операции:

    • updateVersion
    • startBIT (Встроенная самопроверка)
    • changeChannel
    • turnVolumeUp, turnVolumeDown

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

http://domain/tv/ ПОЛУЧИТЬ | PUT — получение или установка volume или channel с помощью объектов json.

и для updateVersion или startBIT:

http://domain/tv/ POST с {function: 'updateVersion'} или {function: 'startBIT'}

Второй вариант заключается в представлении всех операций с использованием ресурса Command:

http://domain/tv/commands POST с {command: 'BIT', sender: 'Dan' .. . } - создать новую команду для выполнения startBIT, changeChannel или turnVolume

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

http://domain/tv/versionUpdates ПОЛУЧИТЬ | ПОСТАВИТЬ | УДАЛИТЬ | СООБЩЕНИЕ

http://domain/tv/BITs ПОЛУЧИТЬ | ПОСТАВИТЬ | УДАЛИТЬ | СООБЩЕНИЕ

http://domain/tv/ PUT ({volume: 10})

http://domain/tv/ PUT ({канал: 29})

Какой дизайн RESTful лучше всего?


person Matan Givoni    schedule 17.10.2015    source источник
comment
Громкость и каналы тоже могут быть ресурсами...   -  person David Brabant    schedule 17.10.2015
comment
@ Дэвид, можно мне один том, пожалуйста? Не все подходит для REST, RPC — одна из таких вещей.   -  person CodeCaster    schedule 17.10.2015
comment
Ресурсы не обязательно соответствуют физическим или конкретным объектам. Настройка громкости: POST /blah/volume/100, изменение канала: PUT /blah/channel/13   -  person David Brabant    schedule 17.10.2015
comment
@David, что на самом деле должно означать POST tv/volume/100, учитывая семантику POST? PUT tv/channel/13 может означать, что вы хотите обновить частоту или описание канала 13, но не означает, что телевизор должен переключиться на этот канал. Почему вы должны использовать два разных глагола для установки текущего состояния двух разных вещей, обе из которых, естественно, могут быть активны только в одно и то же время - если только у вас нет нескольких тюнеров в случае каналов?   -  person CodeCaster    schedule 17.10.2015
comment
@DavidBrabant Это не выглядит очень RESTful, потому что при ссылке на blah/volume/100 похоже, что мы используем глагол a, а RESTful способ - использовать существительные. Ваше предложение очень похоже на blah/changeChannelTo/23 ..   -  person Matan Givoni    schedule 17.10.2015
comment
@Матан. Эм-м-м? Объем - это глагол?   -  person David Brabant    schedule 17.10.2015
comment
Нет, это не так, но посмотрите, что произойдет, если я заменю volume на changeVolumeTo, вы понимаете, что я имею в виду? Если мы отправим сообщение на blah/changeVolumeTo/10, это означает, что у нас плохой дизайн.   -  person Matan Givoni    schedule 17.10.2015


Ответы (1)


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

Изменения, которые я бы применил:

  • http://domain/tv/firmware GET | DELETE | POST

    Я бы изменил versionUpdates на firmware - кажется, это гораздо более информативно. Более того, кажется, что операция PUT здесь не имеет смысла - возможно, вы априори не знаете новую версию прошивки. Итак, GET возвращает текущую версию прошивки, DELETE удаляет последнюю и восстанавливает предыдущую, POST ищет и устанавливает последнюю.

  • http://domain/tv/BITs GET | POST

    Здесь вроде GET и POST хватит. Вам просто нужно GET результаты всех тестов или конкретного или только POST нового теста.

  • http://domain/tv/ PATCH ({volume: 10}) и http://domain/tv/ PATCH ({channel: 29})

    Так как оба очень похожи — я бы изменил PUT на PATCH — помните, что при использовании PUT вам нужно включить весь объект, то есть каждое свойство. PUT также является идемпотентной операцией. При использовании PATCH вы можете изменить только одно свойство.

person Opal    schedule 18.10.2015
comment
Что вы скажете о втором варианте (Команды)? При использовании Commands мы инкапсулируем общие операции с телевизором (хотя кажется, что это уловка для обработки всех операций как одного существительного, слишком общего...). Я согласен с вами насчет использования как можно большего количества существительных (прошивки и BIT). - person Matan Givoni; 18.10.2015
comment
Я рассматриваю команду только как оболочку для операции. Я думаю, что немного неудобно относиться к функции как к ресурсу, особенно потому, что она не будет сохраняться на стороне сервера, а вызывается;) Команда может быть полезна для удаленного управления (если вам нужно ее смоделировать ) - но не как функция, а как ресурс. Я понимаю, что иногда очень сложно моделировать реальный мир с помощью REST, однако мы должны максимально придерживаться общих правил. - person Opal; 19.10.2015
comment
Да, но как вы можете вызвать функцию RESTful? - person Opal; 23.10.2015
comment
Да, я понял, что вызов функций должен выполняться в RESTful, поэтому PUT нового тома, например, в http://domain/tv/, намного RESTfuler. - person Matan Givoni; 23.10.2015