Skip to main content

Миграция из REST в GraphQL

Ознакомьтесь с рекомендациями по миграции из REST API GitHubв API GraphQL GitHub.

Отличия в логике API

GitHub предоставляет два API: REST API и API GraphQL. Дополнительные сведения о API-интерфейсах %% данных variables.product.company_short %}см. в разделе "Сравнение REST API GitHub и API GraphQL".

Миграция из REST в GraphQL сопровождается существенным изменением в логике API. Различия между стилем REST и спецификацией GraphQL затрудняют— и часто делают нежелательной— замену вызовов REST API на запросы API GraphQL один к одному. Ниже приведены примеры миграции.

Чтобы перенести код из REST API в GraphQL API, выполните следующие действия:

К значительным преимуществам GraphQL относятся:

Ниже приведены примеры каждого из них.

Пример: получение только необходимых данных

Один вызов REST API получает список участников вашей организации:

curl -v https://api.github.com/orgs/:org/members

Полезные данные REST содержат избыточную информацию, и какая-то ее часть окажется ненужной, если вам нужно получить только имена членов и ссылки на аватары. Запрос GraphQL, напротив, возвращает только то, что вы указываете:

query {
    organization(login:"github") {
    membersWithRole(first: 100) {
      edges {
        node {
          name
          avatarUrl
        }
      }
    }
  }
}

Рассмотрим другой пример: получение списка запросов на включение внесенных изменений и проверка возможности слияния для каждого из них. Вызов REST API получает список запросов на включение внесенных изменений и их сводные представления:

curl -v https://api.github.com/repos/:owner/:repo/pulls

Чтобы определить, можно ли выполнить слияние для запроса на включение внесенных изменений, требуется получить каждый запрос на включение внесенных изменений по отдельности ради его подробного представления (большой объем полезных данных) и проверить, имеет ли его атрибут mergeable значение true или false:

curl -v https://api.github.com/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 https://api.github.com/repos/:owner/:repo/pulls/:number
curl -v https://api.github.com/repos/:owner/:repo/pulls/:number/commits
curl -v https://api.github.com/repos/:owner/:repo/issues/:number/comments
curl -v https://api.github.com/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
        }
      }
    }
  }
}