Каковы рекомендации для вложенных ресурсов REST



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



возьмем для примера остальные представительства компаний. В этом гипотетическом примере, каждая компания принадлежит 0 или более отделов и каждый отдел принадлежит 0 или более сотрудников.



отдела не существует без ассоциированной компании.



сотрудник не существует без соответствующего департамента.



теперь я бы нашел естественное представление шаблонов ресурсов.





  • /companiesколлекции с - принимает положить для новой компании. Получить за всю коллекцию.


  • /companies/{companyId} отдельная компания. Принимает GET, PUT и DELETE


  • /companies/{companyId}/departments принимает сообщение для нового элемента. (Создает отдел внутри компании.)

  • /companies/{companyId}/departments/{departmentId}/

  • /companies/{companyId}/departments/{departmentId}/employees

  • /companies/{companyId}/departments/{departmentId}/employees/{empId}


учитывая ограничения, в каждом из разделов, я чувствую, что это имеет смысл, если немного глубоко вложены.



однако, моя трудность приходит, если я хочу перечислить (GET) все сотрудники во всех компаниях.



шаблон ресурса для этого будет наиболее близко сопоставляться с /employees (собрание всех сотрудников)



это значит, что что я должен был /employees/{empId} также потому, что если это так, то есть два URI, чтобы получить тот же ресурс?



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



на базовом уровне /employees/?company={companyId}&department={deptId} возвращает точно такое же представление сотрудников, как и наиболее глубоко вложенный шаблон.



какова лучшая практика для шаблонов URL, где ресурсы принадлежащего другими ресурсами, но должны быть запрос-возможность отдельно?





обновление: смотрите мой ответ ниже, чтобы увидеть, что я сделал.

583   6  

6 ответов:

то, что вы сделали правильный. В общем, на одном ресурсе может быть много URI - нет правил, которые говорят, что вы не должны этого делать.

и вообще, вам может понадобиться доступ к элементам напрямую или как часть чего-то другого - так что ваша структура имеет смысл для меня.

только потому, что сотрудники находятся в отделе:

company/{companyid}/department/{departmentid}/employees

не означает, что они не могут быть доступны в компании тоже:

company/{companyid}/employees

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

но я надеюсь, что все обработчики URL-адресов используют один и тот же код поддержки для удовлетворения запросов, чтобы вы не дублировали код.

Я пробовал обе стратегии проектирования-вложенные и не вложенные конечные точки. Я нашел, что:

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

  2. вложенные конечные точки обычно требуют избыточных конечных точек. Другими словами, вам чаще всего понадобится дополнительная конечная точка /employees, чтобы вы могли получить список сотрудников по отделам. Если у вас есть /сотрудники, что именно/компании/отделы / сотрудники покупают вам?

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

  4. иногда ресурс может иметь несколько типов родителей. В результате несколько конечных точек возвращают один и тот же ресурс.

  5. избыточные конечные точки затрудняют написание документов, а также затрудняют изучение api.

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

я переместил то, что я сделал, с вопроса на ответ, где больше людей, вероятно, увидят его.

то, что я сделал, это иметь конечные точки создания во вложенной конечной точке канонической конечной точкой для изменения или запроса элемента является не на вложенном ресурсе.

Итак, в этом примере (просто перечислите конечные точки, которые изменяют ресурс)

  • POST/companies/ создает новую компанию возвращает a ссылка на созданную компанию.
  • POST/companies/{companyId}/departments когда отдел помещается создает новый отдел возвращает ссылку на /departments/{departmentId}
  • PUT/departments/{departmentId} изменяет отдела
  • POST/departments/{deparmentId}/employees создает нового сотрудника возвращает ссылку на /employees/{employeeId}

таким образом, есть ресурсы корневого уровня для каждой из коллекций. Однако создать находится в владеющего

Я не согласен с таким путем

GET /companies/{companyId}/departments

если вы хотите получить отделы, я думаю, что лучше использовать ресурс / departments

GET /departments?companyId=123

полагаю, у вас есть companies таблица и departments таблица затем классы для отображения их на языке программирования, который вы используете. Я также предполагаю, что отделы могут быть прикреплены к другим объектам, чем компании, поэтому ресурс a / departments прост, удобно иметь ресурсы, сопоставленные с таблицами, а также вы не нужно столько конечных точек, так как вы можете повторно использовать

GET /departments?companyId=123

для любого вида поиска, например

GET /departments?name=xxx
GET /departments?companyId=123&name=xxx
etc.

если вы хотите создать отдел,

POST /departments

ресурсы должны использоваться, и тело запроса должно содержать идентификатор компании (если отдел может быть связан только с одной компанией).

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

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

Почему так ? Же далеко как я знаю," RESTful " API должен быть доступен для просмотра (вы знаете..."Гипермедиа как двигатель состояния приложения"), поэтому клиент API не заботится о том, каковы ваши URL-адреса, пока они действительны (нет SEO, нет человека, который должен читать эти" дружественные URL-адреса", за исключением, возможно, для отладки...)

насколько хороший / понятный URL-адрес в REST API интересен вам только как разработчик API, а не клиент API, как и имя переменной в вашем коде быть.

самое главное, что ваш клиент API знает, как интерпретировать ваш тип носителя. Например, он знает, что :

  • ваш тип носителя имеет свойство links, в котором перечислены доступные/связанные ссылки.
  • каждая ссылка идентифицируется отношением (так же, как браузеры знают, что ссылка[rel="таблица стилей"] означает, что ее таблица стилей или rel=favico является ссылкой на фавикон...)
  • и он знает, что эти отношения означают ("компании" означает список компаний, "поиск" означает шаблонный url для выполнения поиска по списку ресурсов, "отделы" означает отделы текущего ресурса)

Ниже приведен пример HTTP exchange (тела находятся в yaml, так как их легче писать):

запрос

GET / HTTP/1.1
Host: api.acme.io
Accept: text/yaml, text/acme-mediatype+yaml

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

HTTP/1.1 200 OK
Date: Tue, 05 Apr 2016 15:04:00 GMT
Last-Modified: Tue, 05 Apr 2016 00:00:00 GMT
Content-Type: text/acme-mediatype+yaml

# body: this is your API's entrypoint (like a homepage)  
links:
  # could be some random path https://api.acme.local/modskmklmkdsml
  # the only thing the API client cares about is the key (or rel) "companies"
  companies: https://api.acme.local/companies
  people: https://api.acme.local/people

запрос: ссылка на компании (используя тело предыдущего ответа.связи.компании)

GET /companies HTTP/1.1
Host: api.acme.local
Accept: text/yaml, text/acme-mediatype+yaml

ответ: частичный список компаний (в разделе items), ресурс содержит связанные ссылки, такие как ссылка для получения следующей пары компаний (body.связи.далее) другая (шаблонная) ссылка для поиска (тело.связи.поиск)

HTTP/1.1 200 OK
Date: Tue, 05 Apr 2016 15:06:00 GMT
Last-Modified: Tue, 05 Apr 2016 00:00:00 GMT
Content-Type: text/acme-mediatype+yaml

# body: representation of a list of companies
links:
  # link to the next page
  next: https://api.acme.local/companies?page=2
  # templated link for search
  search: https://api.acme.local/companies?query={query} 
# you could provide available actions related to this resource
actions:
  add:
    href: https://api.acme.local/companies
    method: POST
items:
  - name: company1
    links:
      self: https://api.acme.local/companies/8er13eo
      # and here is the link to departments
      # again the client only cares about the key department
      department: https://api.acme.local/companies/8er13eo/departments
  - name: company2
    links:
      self: https://api.acme.local/companies/9r13d4l
      # or could be in some other location ! 
      department: https://api2.acme.local/departments?company=8er13eo

так как вы видите, если вы идете по ссылкам/отношениям, как вы структурируете путь часть ваших URL-адресов не имеет никакого значения для вашего клиента API. И если ваш передают структуру ваших URL-адресов вашему клиенту в качестве документации, а затем вы не делаете REST (или, по крайней мере, не Уровень 3 согласно " модель зрелости Ричардсона")

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

в более сложных системах может возникнуть соблазн предоставить URI, которые позволяет клиенту перемещаться по нескольким уровням отношений, например,/customers/1/orders/99/products. однако, этот уровень сложность может быть трудно поддерживать и негибкая, если отношения между ресурсами изменения в будущем. вместо этого попробуйте держите URIs относительно простым. После того как приложение имеет ссылку на ресурс, должна быть возможность использовать эту ссылку для поиска элементов связано с этим ресурсом. Предыдущий запрос можно заменить Ури /customers/1/orders найти все заказы для клиента 1, и тогда /orders/99/products, чтобы найти продукты в таком порядке.

.

Совет

не требуйте более сложных URI ресурсов, чем collection/item/collection.

Comments

    Ничего не найдено.