Каковы рекомендации для вложенных ресурсов 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, где ресурсы принадлежащего другими ресурсами, но должны быть запрос-возможность отдельно?
обновление: смотрите мой ответ ниже, чтобы увидеть, что я сделал.
6 ответов:
то, что вы сделали правильный. В общем, на одном ресурсе может быть много URI - нет правил, которые говорят, что вы не должны этого делать.
и вообще, вам может понадобиться доступ к элементам напрямую или как часть чего-то другого - так что ваша структура имеет смысл для меня.
только потому, что сотрудники находятся в отделе:
company/{companyid}/department/{departmentid}/employeesне означает, что они не могут быть доступны в компании тоже:
company/{companyid}/employeesкоторый вернет сотрудников для этой компании. Это зависит от того, что нужно вашему потребляющему клиенту - это то, для чего вы должны разрабатывать.
но я надеюсь, что все обработчики URL-адресов используют один и тот же код поддержки для удовлетворения запросов, чтобы вы не дублировали код.
Я пробовал обе стратегии проектирования-вложенные и не вложенные конечные точки. Я нашел, что:
Если вложенный ресурс имеет первичный ключ, а у вас нет его родительского первичного ключа, вложенная структура требует, чтобы вы его получили, хотя на самом деле система этого не требует.
вложенные конечные точки обычно требуют избыточных конечных точек. Другими словами, вам чаще всего понадобится дополнительная конечная точка /employees, чтобы вы могли получить список сотрудников по отделам. Если у вас есть /сотрудники, что именно/компании/отделы / сотрудники покупают вам?
конечные точки вложенности не развиваются так хорошо. Например, вам может не понадобиться искать сотрудников сейчас, но вы можете позже, и если у вас есть вложенная структура, у вас нет выбора, кроме как добавить другую конечную точку. С не вложенным дизайном вы просто добавляете больше параметров, что проще.
иногда ресурс может иметь несколько типов родителей. В результате несколько конечных точек возвращают один и тот же ресурс.
избыточные конечные точки затрудняют написание документов, а также затрудняют изучение 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