RESTFul наследование типа носителя

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

Например, я выбрал «application/hal+json» в качестве базового типа мультимедиа. Все, что получит пользователь, будет большим двоичным объектом HAL с некоторыми добавленными полями. Я не хочу называть свои типы мультимедиа просто «application/hal+json», мне кажется, что должно быть доступно больше информации, чем это, но я хочу, чтобы было ясно, что это то, чем они являются в дополнение к дополнительным полям. это мои данные. Кроме того, моя система в конечном итоге будет иметь некоторые из этих полей, унаследованных как в формате запроса (который не будет HAL blobs), так и в формате ответа. Общий тип «Пользователь» может иметь только идентификатор пользователя и имя, например, в то время как расширение, такое как «Студент» или «Учитель», будет иметь другие дополнительные поля.

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


person Edward Strange    schedule 20.07.2014    source источник
comment
Ваш вопрос не очень ясен. Вы спрашиваете, имеет ли смысл для медиа-типа «Студент» не иметь полей «Пользователь» и вместо этого ссылаться на ресурс «Пользователь», содержащий эти поля?   -  person Pedro Werneck    schedule 21.07.2014


Ответы (2)


Несколько вещей, которые я хотел бы отметить о вашем переходе на настоящую архитектуру RESTful.

Во-первых, RESTful API должны выполнять согласование содержимого. Сказать, что ваш базовый тип — hal+json, кажется странным. Похоже, вы хотите иметь такие типы, как parent+hal+json или, может быть, hal+json;type=parent. Это означало бы, что ваш клиент должен был бы специально понимать эти типы... и это было бы не очень RESTful, потому что это просто локальная реализация. Это нормально в реальном мире... вы можете сделать это... почти все делают подобные вещи.

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

Теперь, конкретно для HAL, вам доступны две вещи, чтобы ваш клиент мог «обнаружить», какие типы данных они возвращают. Один из них — CURIE, а другой — профили http://tools.ietf.org/html/draft-kelly-json-hal-06#section-5.6 Я думаю, что Profiles — это то, что вам нужно здесь, поскольку они позволяют вам документировать соглашения и ограничения для ресурса, который будет получено.

Но не сбрасывайте со счетов и КЮРИ. Там уже есть много определенной семантики. Ваша модель может соответствовать одному из наборов http://schema.org, и тогда вы можете просто использовать их отношения ссылок, а клиент должен знаю, что происходит.

Если вам действительно нужен большой контроль над семантикой ваших ресурсов... вы можете посмотреть на http://json-ld.org/ с его концепцией @context будет хорошей ссылкой.

На мой взгляд, это область, где примеров очень мало, особенно для HAL. Я еще не видел клиента, достаточно умного, чтобы анализировать и заботиться о семантике во время выполнения. Что я считаю важным, так это то, что когда кто-то создает клиент, доступная информация, он может понять, что Студент - это Человек. Однажды вещь, создающая клиентов, станет кодом генератора клиентов, и он будет использовать эту информацию для создания для вас хорошей объектной модели на стороне клиента.

TL; DR, если вы придерживаетесь HAL, используйте CURIE и Profiles, чтобы получить то, что вы хотите.

person Chris DaMour    schedule 06.08.2014

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

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

При этом разные клиенты (и, если на то пошло, разные инженеры) по-разному относятся к лучшим практикам. Например, если вы пытаетесь найти пользователя по электронной почте, есть как минимум два подхода.

1) GET /users/emails/{email} // Клиент может интерпретировать это как "получение пользователя по электронной почте"

2) GET /users?email={email} // Клиент может интерпретировать это как "поиск пользователя по электронной почте" из-за параметра запроса

3) GET /users/email={email} // Это можно интерпретировать так же, как # 1

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

Теперь конкретно по вашим вопросам. Вот как будет выглядеть мой подход с точки зрения «User», «Student» и «Teacher».

Я смотрю на каждый из этих 3-х как на отдельные ресурсы? Почему? потому что это отдельные типы, хотя 2 из них расширены из 3-го. Теперь, как мой API будет выглядеть для них?

Для студента:

1) Получение списка студентов: GET /students

2) Получение студента с идентификатором: GET /students/{id}

3) Создание ученика: POST /students

4) Обновление учащегося: PUT /students/{id}

5) Удалить учащегося: УДАЛИТЬ /students/{id}

6) Найдите ученика: GET /students?{whateverQueryParamsYouWantForSearch}

То же самое относится и к Учителю.

А теперь User.

1) GET /users : Получение списка всех пользователей (Students и Teachers)

2) GET /users?type={type} : Вот кикер. Вы можете указать тип ученика или учителя, и вы вернете данные определенного типа (должным образом задокументированные, конечно).

3) POST /users?type={type} : создать определенный ТИП пользователя (student или teacher)

.. И так далее.

Основное отличие заключается в том, что API с корневым URL-адресом /users может использоваться для ОБОИХ типов пользователей (при условии, что тип всегда указывается и документируется для клиентов). В то время как API Student и Teacher специфичны для этих типов.

Мои деньги всегда были на определенные типы, в то время как общие типы для поиска (имеется в виду поиск обоих типов пользователей .. используйте /users?params). Это самый простой способ для клиентов понять, что происходит. Даже задокументировать их намного проще.

Наконец, поговорим о HATEOAS. Да, это часть стандартов, и рекомендуется ВСЕГДА предоставлять URL-адрес/ссылку на ресурс, который вы возвращаете, или если ваш возвращаемый объект сложен и содержит другие ресурсы, которые могут содержать ресурсы, которые сами могут быть доступны через API. Например,

/users?type=student&[email protected]

вернет всех пользователей с этим адресом электронной почты, и лучше следовать HATEOAS здесь и предоставить URL-адрес каждому возвращаемому пользователю, чтобы URL-адрес выглядел так: /students/{id}. Вот как мы обычно обращались с HATEOAS

Это все, что я должен добавить. Как я уже говорил ранее, это очень открытая дискуссия. Каждый инженер интерпретирует стандарты по-своему, и нет ОДНОГО СПОСОБА для обработки всех вариантов использования. Есть некоторые базовые правила, и клиенты и другие разработчики будут вам аплодировать, если вы будете им следовать :)

person shahshi15    schedule 20.07.2014
comment
Извините, но этот ответ явно неверен. Семантика URI не имеет отношения к REST. Может быть допустимой практикой HTTP иметь четкую семантику URI, но совершенно абсурдно говорить, что очень важно, чтобы клиент мог понять, что происходит с URI. Это вообще не важно, в этом смысл использования HATEOAS. - person Pedro Werneck; 21.07.2014
comment
Как я уже упоминал в самом ответе, у каждого разработчика свои взгляды. Среди них нет правильных/неправильных. С точки зрения спецификаций REST я согласен с вами, но как разработчик, использовавший множество API для отдыха, я абсолютно точно с вами не согласен. Вы когда-нибудь задумывались о таких URL-адресах, как /abc/{id}/{anohterId}/giveMeCounts? Не издевайтесь над вашим комментарием, но URL-адреса важны для реализации, даже если спецификации могут быть нестрогими. - person shahshi15; 23.07.2014
comment
Я никогда не говорил, что URI не важны для реализации. Я сказал, что вы ошибаетесь, когда говорите, что службы REST сильно зависят от семантики URI. Это абсурд, и в этом нет никакой субъективности, чтобы вы сказали, что это личная точка зрения. Если взаимодействие с клиентом зависит от семантики URI, оно связано с протоколом и позволяет внеполосной информации управлять взаимодействием. - person Pedro Werneck; 23.07.2014
comment
Ваше отношение к HATEOAS как к маловажной побочной проблеме является отражением этого, особенно учитывая, насколько это важно для заданного вопроса. Если вы не используете HATEOAS, вы не используете REST, а если вы используете HATEOAS, содержимое URI вообще не важно для пользовательского агента. Я полагаю, что вы использовали множество API-интерфейсов REST, но вам следует глубже изучить этот вопрос и узнать, что большинство так называемых API-интерфейсов REST вообще не являются REST. В процессе вы многому научитесь, гарантирую. - person Pedro Werneck; 23.07.2014
comment
Я думаю, что вы неправильно интерпретируете мои ответы и, вероятно, неправильно понимаете, что я говорю. Вот что я сказал о HATEOAS: Наконец-то поговорим о HATEOAS. Да, это часть стандартов, и рекомендуется ВСЕГДА предоставлять URL-адрес/ссылку на ресурс, который вы возвращаете, или если ваш возвращаемый объект сложен и содержит другие ресурсы, которые могут содержать ресурсы, которые сами могут быть доступны через API. Мой ответ касался заданного вопроса, а не HATEOAS. Если вы хотите обсудить HATEOAS, создайте для этого отдельную тему. - person shahshi15; 24.07.2014
comment
Вопрос о HATEOAS. - person Pedro Werneck; 24.07.2014
comment
@xmenymenzmen здесь я согласен с Педро. URI не должны иметь значения в действительно RESTful архитектуре. Думаю, вы могли бы начать свой ответ с того, что это не ответ, а просто мое мнение. - person Chris DaMour; 06.08.2014
comment
Учиться чему-то известному каждый день :). Спасибо за вклад! - person shahshi15; 19.08.2014