Лучшие практики для конкретных сценариев в RESTful Services - PullRequest
7 голосов
/ 05 июля 2011

У меня два быстрых вопроса, на которые я просто хочу узнать мнение сообщества -

  1. Если у меня есть объект, доступ к которому можно получить либо с помощью идентификатора, либо с датой (20110705), какова наилучшая практика для соглашения URL, используемого для доступа к объекту?

    • GET: /myEntities/{date} и /myEntities/{id}? (который Служба проанализирует {объект}, чтобы проверить, является ли это датой или идентификатором.

    • GET: /myEntities/date/{date} и /myEntities/id/{id}*?

  2. В WCF Rest я также могу сделать /myEntities/?date={date} и /myEntities/?id={id}, это хорошая практика REST? Другими словами, допустимо ли с точки зрения передового опыта использовать ?date={date} вместо date/{date}/, как будто это просто личное предпочтение?

Заранее спасибо.

Ответы [ 3 ]

8 голосов
/ 05 июля 2011

Я чувствую, что многое из этого сводится к предпочтениям и стилю.

Сказав это, я бы лично предпочел:

/myEntities/date/{date} и /myEntities/{id}

Нет необходимости явно указывать опцию ID; это предполагается.

В отношении # 2; Лично мне не нравится этот синтаксис: /myEntities/?date={date} , если он реализован в WCF в качестве шаблона URI - потому что, если у вас есть более одного параметра, предполагается, что порядок параметров может быть разбит вокруг - но они не могут с шаблоном URI. Но в качестве стандартных параметров строки запроса это вполне приемлемо, и это делается повсеместно - Google, Yahoo, Amazon и другие используют этот стиль. Во всяком случае, это именно то, для чего предназначалась «строка запроса» - параметры для запроса ... именно это вы и делаете при извлечении сущностей с помощью __ .

(Но мне так же, как и вам, любопытно, что скажут другие).

6 голосов
/ 06 июля 2011

/myEntities/date/{date} следует перенаправить на /myEntities/{id}, используя 301 или 307, в зависимости от вашего приложения. Это уменьшает возможность синхронизации данных из-за нескольких кэшированных копий и дает понять клиентам, что /myEntities/date/* - это просто альтернативный индекс, а не набор независимых ресурсов (как они могли бы ожидать, если вы не перенаправили из-за иерархической природы HTTP URI).

0 голосов
/ 19 февраля 2015

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

Это также означает, что у вас никогда не будет двух URL, которые однозначно идентифицируют один и тот же ресурс.

Теперь это не значит, что вы не можете получить доступ к одному и тому же ресурсу с двух разных URL. Есть много причин, почему вы хотели бы сделать это. Есть только несколько вещей, в которых вы должны убедиться.

Вы должны сделать это очень легко понятным для любого, кто использует ваш API, что происходит. Опции, которые вы перечислили, не делают этого.

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

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

Мне тоже не нравится предложение Стива. Как потребитель узнает, что вы можете написать «дату» вместо идентификатора, а затем внезапный доступ по дате? Это не интуитивно понятно.

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

В качестве альтернативы рассмотрите что-то вроде:

/years, который может предоставить список объектов года

{
  "year": 2015,
  "entities": "https://api.myapp.com/years/2015/entities",
  "months": [
      {
        "month": 1,
        "name": "January",
        "entities": "https://api.myapp.com/years/2015/months/1/entities",
        "self": "https://api.myapp.com/years/2015/months/1"
      },
       ... array of month objects
  ],
  "self": "https://api.myapp.com/years/2015"
}

/years/2015/months/1 является одним примером объекта месяца

{
  "month": 1,
  "name": "January",
  "entities": "https://api.myapp.com/years/2015/months/1/entities",
  "self": "https://api.myapp.com/years/2015/months/1"
}

Свойство entity имеет ссылку на коллекцию объектов, отфильтрованных по дате.

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

...