Отличия в логике API
GitHub предоставляет два API: REST API и API GraphQL. Дополнительные сведения о см. в разделе Сравнение REST API GitHub и API GraphQL.
Миграция из REST в GraphQL сопровождается существенным изменением в логике API. Различия между стилем REST и спецификацией GraphQL затрудняют— и часто делают нежелательной— замену вызовов REST API на запросы API GraphQL один к одному. Ниже приведены примеры миграции.
Чтобы перенести код из REST API в GraphQL API, выполните следующие действия:
- ознакомьтесь со спецификацией GraphQL;
- ознакомьтесь со схемой GraphQL в GitHub;
- проанализируйте, как существующий код взаимодействует с REST API в GitHub;
- используйте идентификаторы глобальных узлов для ссылки на объекты в разных версиях API.
К значительным преимуществам GraphQL относятся:
Ниже приведены примеры каждого из них.
Пример: получение только необходимых данных
Один вызов REST API получает список участников вашей организации:
curl -v http(s)://HOSTNAME/api/v3/orgs/:org/members
Полезные данные REST содержат избыточную информацию, и какая-то ее часть окажется ненужной, если вам нужно получить только имена членов и ссылки на аватары. Запрос GraphQL, напротив, возвращает только то, что вы указываете:
query {
organization(login:"github") {
membersWithRole(first: 100) {
edges {
node {
name
avatarUrl
}
}
}
}
}
Рассмотрим другой пример: получение списка запросов на включение внесенных изменений и проверка возможности слияния для каждого из них. Вызов REST API получает список запросов на включение внесенных изменений и их сводные представления:
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls
Чтобы определить, можно ли выполнить слияние для запроса на включение внесенных изменений, требуется получить каждый запрос на включение внесенных изменений по отдельности ради его подробного представления (большой объем полезных данных) и проверить, имеет ли его атрибут mergeable
значение true или false:
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number
При использовании GraphQL для каждого запроса на включение внесенных изменений можно получить только необходимые атрибуты number
и mergeable
:
query {
repository(owner:"octocat", name:"Hello-World") {
pullRequests(last: 10) {
edges {
node {
number
mergeable
}
}
}
}
}
Пример: вложенные поля
Благодаря поддержке запросов с вложенными полями можно заменить несколько вызовов REST на меньшее количество запросов GraphQL. Например, получение запроса на включение внесенных изменений вместе с его фиксациями, комментариев без проверки и проверок с помощью REST API требует четырех отдельных вызовов:
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number/commits
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/issues/:number/comments
curl -v http(s)://HOSTNAME/api/v3/repos/:owner/:repo/pulls/:number/reviews
С помощью API GraphQL эти данные можно получить с помощью одного запроса с вложенными полями:
{
repository(owner: "octocat", name: "Hello-World") {
pullRequest(number: 1) {
commits(first: 10) {
edges {
node {
commit {
oid
message
}
}
}
}
comments(first: 10) {
edges {
node {
body
author {
login
}
}
}
}
reviews(first: 10) {
edges {
node {
state
}
}
}
}
}
}
Эффективность этого запроса можно увеличить, заменив номер запроса на включение внесенных изменений на переменную .
Пример: строгая типизация
Схемы GraphQL строго типизированы, что делает обработку данных безопаснее.
Рассмотрим добавление комментария к проблеме или запросу на включение внесенных изменений с помощью изменения GraphQL, когда для значения clientMutationId
по ошибке было указано целое число вместо строки:
mutation {
addComment(input:{clientMutationId: 1234, subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
clientMutationId
commentEdge {
node {
body
repository {
id
name
nameWithOwner
}
issue {
number
}
}
}
}
}
При выполнении этого запроса возвращаются ошибки с указанием ожидаемых типов для операции:
{
"data": null,
"errors": [
{
"message": "Argument 'input' on Field 'addComment' has an invalid value. Expected type 'AddCommentInput!'.",
"locations": [
{
"line": 3,
"column": 3
}
]
},
{
"message": "Argument 'clientMutationId' on InputObject 'AddCommentInput' has an invalid value. Expected type 'String'.",
"locations": [
{
"line": 3,
"column": 20
}
]
}
]
}
Если заключить 1234
в кавычки, значение будет преобразовано из целого числа в строку ожидаемого типа:
mutation {
addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
clientMutationId
commentEdge {
node {
body
repository {
id
name
nameWithOwner
}
issue {
number
}
}
}
}
}