Как сделать REST-фул обновления? - PullRequest
7 голосов
/ 12 декабря 2011

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

Что такое способ REST-fullструктурирование API?Я предполагаю, что правильным методом является POST.

Меня беспокоит то, что пользователю кажется не совсем элегантным сначала получить обе части объекта (рейтинг производительности и контактную информацию), обновить только одну часть и POST полностью обновитьobject.

Другая моя проблема заключается в том, что отправка объекта с только определенными полями кажется неэффективной, поскольку схема для объекта требует заполнения всех полей, а пропуск полей только для поддержки POST.,И. е.потребовались бы отдельные схемы только для поддержки операций или обхода без схем - ни одна из них не кажется правильной.

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

Предоставление отдельных методов никоим образом не вписывается в парадигму существительных-глаголов.

КАК должны выглядеть API-интерфейсы REST, когда они необходимы для обработки таких случаев?Должно ли быть соответствие «многие к одному» между существительными REST и сущностями приложения?Если да, то ограничиваем ли мы PUT для сущностей представлений, которые будут представлять подмножества сущностей приложений?

Я не ищу взлома или неэкранированного способа.Я ищу то, что философия REST посчитала бы правильным решением.Заранее спасибо!

Ответы [ 5 ]

4 голосов
/ 12 декабря 2011

Я не уверен, что это противоречит вашим опасениям, но, учитывая, что Rating и Info также являются ресурсами, я бы сделал API таким (спасибо taylonr за шаблон:)

url/employees/{id}/[rating|info]

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

Создание нового сотрудника с инициализированной контактной информацией и рейтингом производительности

POST url/employees { "id": "johnsmith", "rating": 4, "info": ["address": "street 1 a 1" , "email": "johns.old@mail.com"] }

Обновление 2 будет работать с разными POST

PUT url/employees/johnsmith/rating  { "rating": 5 }
PUT url/employees/johnsmith/info { "email": "john.smith@company.com" }
3 голосов
/ 12 декабря 2011

Полагаю, это зависит от того, как это предполагается использовать.

Если вы просто собираетесь что-то сделать, например, просто передать клиенту ВСЕ данные, необходимые для обновления объекта ВЕСЬ сотрудник, тогда вам нужно будет предоставить только одну конечную точку, и вы можете просто сделать ...

domain/employee/{employee_id}

Как объяснил @taylonr. Это более вероятный сценарий для API, который вы предоставляете третьим лицам. Причина, по которой вы создадите такой метод, заключается в том, что он позволяет третьим сторонам создавать свои собственные функции для обновления всего ресурса; а затем передать это вам. Другими словами, наличие всего доступного ресурса - хороший улов для всех; но, вероятно, не самый лучший, если вы используете его для собственного веб-приложения.

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

domain/employee/{employee_id}/action

Так, например, когда я проголосовал за ваш пост, пост, который Stackoverflow использует под капотом, был ....

                         noun    noun verb verb
                           |       |     |  | 
                           |       |     |  |
http://stackoverflow.com/posts/8478829/vote/2

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

Вы сказали, что

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

но я не думаю, что это серьезная проблема. Вместо того, чтобы полагаться на то, что клиент передаст всю информацию для объекта, который он хотел бы обновить, вы просто используете часть «существительное» - posts/8478829 = и разрешите сторону сервера ресурсов.

2 голосов
/ 12 декабря 2011

Другой вариант - использовать относительно новый PATCH HTTP-глагол и собственную схему для вашего формата patch / diff.Это позволяет избежать загрязнения семантики PUT / POST и более точно соответствовать тому, что вам нужно, то есть обновить подмножество атрибутов ресурса.

В противном случае, я бы пошел с подходом Topi Ojala (замена PUT/ POST как кто-то уже прокомментировал)

2 голосов
/ 12 декабря 2011

PUT на тот же URI, с которого вы получаете.

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

Если я пользователь вашего API, мне действительно все равно, что вы делаете или не рассматриваете сущность в своей реализации, мне важно, что вы считаете ресурсом в своем веб-сервисе.

2 голосов
/ 12 декабря 2011

Почему бы просто не сделать

PUT myuri/Employee/{id}

И тело запроса имеет объект Employee.Таким образом, потребитель обновляет все, что хочет, и возвращает его вам.Поскольку у пользователя уже есть идентификатор, вы можете сделать PUT.

Вот как мы обычно делаем это с API, над которыми я работал.

Преимущество возврата всего объекта заключается в том, чтопотому что API должен знать, является ли версия, которую имеет пользователь, самой последней (например, с ETag).Если потребитель пытается обновить что-то устаревшее, это должно привести к сбою.

...