Знакомство с графовыми API

Автор: admin от 16-02-2018, 15:35, посмотрело: 119

Привет, Хабр!



Мы не перестаем отслеживать тему проектирования API после того, как встретили в портфеле издательства «Manning» вот эту книгу. Сегодня мы решили опубликовать обзорную статью об относительно новых Graph API и предлагаем еще раз задуматься о том, каковы будут новые API после безраздельной популярности REST.



Приятного чтения!

своего API в 2010 году и с тех пор проектирует новые версии, вдохновляясь примером графовых баз данных. Существуют узлы, соответствующие, например, постам и комментариям, а также ребра, соединяющие их и указывающие, что данный комментарий «относится» к этому посту. Такой подход обеспечивает всей конструкции не менее качественную обнаружимость, чем у типичного REST API, однако, все равно позволяет клиенту оптимизировать извлечение данных. Возьмем в качестве примера отдельный пост и рассмотрим, какие простые операции можно с ним проделать.



Для начала клиент при помощи запроса GET выбирает пост из корня API, исходя из ID поста.



GET /<post-id>


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



GET /<post-id>?fields=caption,created_time


Чтобы выбрать требуемые данные, клиент запрашивает ребро, например, комментарии к посту:



GET /<post-id>/comments


До сих пор все это напоминает функции REST API. Пожалуй, возможность задать подмножество полей – в новинку, но в целом данные воспринимаются во многом как ресурсы. Ситуация становится интереснее, когда клиент собирает вложенный запрос. Вот как еще клиент может выбрать комментарии к посту:



GET /<post-id>?fields=caption,created_time,comments{id,message}


Вышеприведенный запрос возвращает отклик, в котором содержится время создания поста, его заголовок и список комментариев (из каждого сообщения выбирается только id и сообщение). В REST вы бы такое сделать не смогли. Клиенту потребовалось бы сначала выбрать пост, а затем — комментарии.



А что, если клиенту потребуются более глубокие вложения?



GET /<post-id>?fields=caption,created_time,comments{id,message,from{id,name}}


В этом запросе выбираются комментарии к посту, в том числе, id и имя автора каждого комментария. Рассмотрим, как это делалось бы в REST. Клиенту потребовалось бы запросить пост, запросить комментарии, а затем в серии отдельных запросов извлечь информацию об авторе каждого комментария. Сразу набирается множество HTTP-вызовов! Однако, при проектировании в виде графа вся эта информация конденсируется в одном вызове, и в этом вызове оказывается лишь та информация, что нужна клиенту.



Наконец, последний момент, который следует отметить о графовом проектировании: любой объект, выбираемый с ребра, сам является узлом и, следовательно, его можно запросить непосредственно. Вот, например, как выбирается дополнительная информация о конкретном комментарии:



GET /<comment-id>


Обратите внимание: клиенту не нужно собирать URL вида /posts//comments/, как могло бы потребоваться при работе с REST API. Это может пригодиться в ситуациях, когда у клиента нет непосредственного доступа к id родительского объекта.



Такая же ситуация возникает при изменении данных. Например, если нам надо обновить и/или удалить объект (скажем, комментарий), применяется запрос PUT или DELETE соответственно, посылаемый непосредственно на конечную точку id. Чтобы создать объект, клиент может направить POST к соответствующему ребру узла. Так, чтобы добавить комментарий к посту, клиент делает запрос POST к ребру с комментариями от этого поста:



POST /<post-id>/comments
message=This+is+a+comment


Кейс 2: GitHub V4 GraphQL API



Другим конкурентом графового API можно считать спецификацию под названием GraphQL. Эта концепция значительно отличается от REST, здесь предоставляется всего одна конечная точка, принимающая запросы GET и POST. При всех взаимодействиях с API отправляются запросы, соответствующие синтаксису GraphQL.



В мае 2017 года GitHub выпустил 4-ю версию своего API, соответствующую этой спецификации. Чтобы попробовать, каков из себя GraphQL, давайте рассмотрим отдельные операции, которые можно проделать с репозиторием.



Чтобы выбрать репозиторий, клиент определяет запрос GraphQL:



POST /graphql

{
  "query": "repository(owner:"zapier", name:"transformer") {
    id
    description
  }"
}


В данном запросе выбирается ID и описание репозитория “transformer” с ресурса Zapier org. Здесь следует отметить несколько вещей. Во-первых, мы считываем данные с API при помощи POST, поскольку посылаем в запросе тело сообщения. Во-вторых, полезная нагрузка самого запроса записана в формате JSON, что предписано в стандарте GraphQL. В-третьих, структура запроса будет именно такой, какая указана в нашем запросе, {"data": {"repository": {"id": "MDEwOlJlcG9zaXRvcnk1MDEzODA0MQ==", "description": "..."}}} (корневой ключ data – еще один обязательный элемент, который должен присутствовать в откликах GraphQL).



Чтобы выбрать данные, относящиеся к репозиторию – например, задачи и их авторов, клиент применяет вложенный запрос:



POST /graphql

{
  "query": "repository(owner: "zapier", name: "transformer") {
    id
    description
    issues(last: 20, orderBy: {field: CREATED_AT, direction: DESC}) {
      nodes {
        title
        body
        author {
          login
        }
      }
    }
  }"
}


Этот запрос выхватывает ID и описание репозитория, название и текст последних 20 задач, созданных в репозитории, а также логин (имя) автора каждой задачи. То есть, в каждом запросе укладывается масса информации. Вообразите, как выглядел бы REST-эквивалент такого запроса – и становится понятно, какие возможности и гибкость обеспечивает клиентам GraphQL в данном отношении.



При обновлении данных GraphQL использует концепцию под названием «мутация». В отличие от REST, где обновление выполняется путем PUT или POST измененной копии ресурса на ту же конечную точку, с которой клиент ее извлек, мутация GraphQL – это явная операция, определяемая API. Если клиенту требуется подкорректировать данные, то требуется знать, какие мутации поддерживаются на сервере. Удобно, что GraphQL позволяет обнаруживать их в рамках процесса под названием «интроспекция схемы».



Прежде, чем обсудить, что такое «интроспекция», нужно прояснить термин «схема». В GraphQL каждый API определяет набор типов, используемых при валидации запросов. До сих пор в GitHub мы работали с типами repository, issue и author. Каждый тип описывает данные, которые в нем содержатся, а также взаимосвязи этого типа с другими. В совокупности все эти типы образуют схему API.



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



Если клиенту требуется узнать, какие мутации возможны в GitHub, можно просто запросить:



POST /graphql

{
  "query": "__type(name: "Mutation") {
    name
    kind
    description
    fields {
      name
      description
    }
  }"
}


Среди мутаций, перечисленных в отклике, находим, например, addStar, позволяющую клиенту проставить звездочку репозиторию (или любому рейтингуемому объекту). Чтобы осуществить мутацию, используется подобный запрос:



POST /graphql
{
  "query": "mutation {
    addStar(input:{starrableId:"MDEwOlJlcG9zaXRvcnk1MDEzODA0MQ=="}) {
      starrable {
        viewerHasStarred
      }
    }
  }"
}


В этом запросе указано, что клиент собирается применить мутацию addStar и предоставляет аргументы, необходимые для выполнения такой операции; в данном случае, это лишь ID репозитория. Обратите внимание: в данном запросе в качестве префикса запроса используется ключевое слово mutation. Так GraphQL узнает, что клиент собирается выполнить мутацию. Во всех предыдущих запросах в качестве префикса также можно было поставить ключевое слово query, но его принято использовать, если тип операции не указан. Наконец, необходимо отметить, что клиент полностью контролирует данные, содержащиеся в отклике. В данном запросе клиент требует из репозитория поле viewerHasStarred – в данном сценарии оно нас не слишком интересует, поскольку при мутации добавляется звездочка, и мы знаем, что она вернет true. Однако, если клиент совершил иную мутацию – скажем, создал задачу, то может получить в ответ сгенерированные значения, например, ID или номер задачи, а также вложенные данные, например, общее количество открытых задач в данном репозитории.



API будущего



Надеюсь, эти кейсы наглядно демонстрируют, как развивается дизайн API в SaaS-индустрии. Я не пытаюсь сказать, что за графовыми API будущее, а REST мертв. В таких архитектурах как GraphQL есть собственные проблемы. Но хорошо, что круг возможностей ширится, и в следующий раз, когда вам потребуется создать API, вы сможете взвесить все компромиссы, на которые приходится идти при том или ином варианте дизайна, и выбрать оптимальное решение.

Источник: Хабрахабр

Категория: Программирование

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

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *