Дизайн API веб-служб REST

Просто хотел получить отзывы о том, как я планирую архитектовать свой API. Ниже приведены методы манекена. Здесь структура:

GET http://api.domain.com/1/users/ <-- returns a list of users
POST http://api.domain.com/1/users/add.xml <-- adds user
POST http://api.domain.com/1/users/update.xml <-- updates user
DELETE (or POST?) http://api.domain.com/1/users/delete.xml <-- deletes user

Вопросы:

  • Можно ли использовать только GET и POST?
  • Является ли хорошей идеей, что я планирую полагаться на имя файла, чтобы указать, какую операцию делать (например, add.xml для добавления)? Было бы лучше сделать что-то вроде этого: POST http://api.domain.com/1/users/add/data.xml?
  • Какой хороший способ сохранить эти ресурсы версиями? В моем примере я использую имя домена /1/after для обозначения версии 1. Альтернативами будут: http://api1.domain.com... или http://api-1.domain.com... или http://apiv1.domain.com... или http://api-v1.domain.com... или http://api.domain.com/v1/... или
  • Какой лучший способ аутентификации?

Ответы

Ответ 1

1) На ваш дизайн, вероятно, нет. POST не является идемпотентным! Поэтому вы не должны использовать для обновления или удаления, вместо этого используйте PUT и DELETE из Rest

2). Лучше всего использовать заголовок Content-Type для WS-вызова, например: application/xml

3) Также в заголовке Content-Type вы можете использовать его: application-v1.0/xml

4) Не уверен, что это лучший, но, вероятно, самый простой способ - использовать встроенные механизмы аутентификации HTTP в RFC 2617. Пример: Аутентификация AWS

Ответ 2

Прежде чем врываться в REST, вот некоторые термины, которые вам действительно нужно понять:

Ресурс - вещи/данные, которые вы хотите сделать доступными в своем API (в вашем случае "пользователь" )

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

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

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

Возьмем пример реального мира. Меня зовут Натан. "Натан" можно считать моим удостоверением (или в спокойных терминах URI), для целей этого примера предположим, что я единственный "Натан" ). Мое имя/идентификатор не изменяется в зависимости от того, как вы хотели бы взаимодействовать со мной, например. Мое имя не изменилось бы на "NathanSayHello", когда вы хотели бы поприветствовать меня.

То же самое для REST. Ваш пользователь, идентифицированный http://api.domain.com/users/1, не изменяется на http://api.domain.com/users/1/update.xml, если вы хотите обновить этого пользователя. Тот факт, что вы хотите обновить этого пользователя, подразумевается с помощью метода, который вы используете (например, PUT).

Вот мое предложение для ваших URI

# Retrieve info about a user 
GET http://api.domain.com/user/<id>

# Retrieve set all users
GET http://api.domain.com/users

# Update the user IDed by api.domain.com/user/<id>
PUT http://api.domain.com/user/<id>

# Create a new user.  The details (even <id>) are based as the body of the request
POST http://api.domain.com/users

# Delete the user ID'd by api.domain.com/user/<id>
DELETE http://api.domain.com/user/<id>

Что касается ваших вопросов:

  • Используйте PUT и DELETE, когда это необходимо, и избегайте перегрузки POST для обработки этих функций, поскольку это нарушает определение HTTP POST. HTTP - это ваш единый интерфейс. Это ваш контракт с пользователем API о том, как они могут взаимодействовать с вашим сервисом. Если вы нарушите HTTP, вы нарушите этот контракт.

  • Удалить "добавить" вообще. Используйте заголовок HTTP Content-Type для указания опубликованных данных типа mime.

  • Вы имеете в виду версию вашего API или версию ресурса? ETag и другие заголовки ответов могут использоваться для версии ресурсов.

  • Здесь много вариантов. Базовый HTTP-аут (простой, но небезопасный), Digest Auth, пользовательский auth, такой как AWS. OAuth также является возможностью. Если безопасность важна, я использую SSL-сертификаты на стороне клиента.

Ответ 3

  • В REST HTTP- "глагол" используется для обозначения типа операции: вы не сможете выразить все операции CRUD только с "GET" и "POST"

  • нет: URL-адрес ресурса обычно находится там, где должен отображаться "идентификатор документа"

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

Конечно, есть много вариаций по теме...

Ответ 4

Я сделал аутентификацию на основе заголовков. Что-то вроде

X-Username:happy-hamster
X-Password:notmyactualpassword

Если вас беспокоит безопасность - сделайте это через SSL. Разумеется, существуют и другие реализации. Например, Amazon с их S3: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html

Если у вас нет возможности делать запросы PUT и DELETE, считается хорошей практикой туннелировать их через POST. В этом случае действие указывается в URL-адресе. Если я правильно помню, RoR делает именно это:

POST http://example.com/foos/2.xml/delete

или

POST http://example.com/foos/3.xml/put

...

<foo>
    <bar>newbar</bar>       
</foo>

Это немного, но в отношении версий и REST в целом вы можете взглянуть на CouchDB. Вот хорошая книга доступна в режиме онлайн