Skip to main content

Эта версия GitHub Enterprise Server будет прекращена 2026-08-25. Снятые релизы не поддерживаются. Исправления выпускаться не будут даже при критических проблемах безопасности. Для лучшей производительности, повышения безопасности и новых функций GitHub Enterprise Server см. Обзор процесса обновления. Для помощи с обновлением обращайтесь в GitHub Enterprise Support.

Формирование вызовов с помощью GraphQL

Узнайте, как выполнить проверку подлинности в API GraphQL, а затем узнайте, как создавать и выполнять запросы и изменения.

Проверка подлинности с помощью GraphQL

Вы можете аутентифицироваться в API GraphQL с помощью personal access token, GitHub App, или OAuth app.

Аутентификация с помощью personal access token

Для аутентификации personal access tokenс помощью , следуйте шагам в Управление личными маркерами доступа. Запрашиваемые данные определяют, какие области или разрешения потребуются.

Например, выберите разрешение "issues:read", чтобы прочитать все проблемы в репозиториях, к которым ваш токен имеет access.

Все fine-grained personal access tokens имеют доступ к публичным репозиториям. Чтобы получить доступ к публичным репозиториям с personal access token (classic)помощью , выберите область действия "public_repo".

Если у вашего токена нет необходимых областей объёмов или разрешений для access к ресурсу, API выдаст сообщение об ошибке с указанием области или разрешений, которые нужны вашему токену.

Аутентификация с помощью GitHub App

Если вы хотите использовать API от имени организации или другого пользователя, GitHub рекомендуется использовать GitHub App. Чтобы атрибутировать действие для приложения, можно выполнить проверку подлинности приложения в качестве установки приложения. Чтобы атрибутировать действие приложения пользователю, можно выполнить проверку подлинности приложения от имени пользователя. В обоих случаях вы создайте маркер, который можно использовать для проверки подлинности в API GraphQL. Для получения дополнительной информации см. Регистрация приложения GitHub и Об аутентификации с помощью приложения GitHub.

Аутентификация с помощью OAuth app

Для аутентификации с помощью токена OAuth OAuth appиз , сначала необходимо авторизировать OAuth app использование веб-приложения или device flow. Затем вы можете использовать полученный токен access для access к API. Для получения дополнительной информации см. Создание приложения OAuth и Авторизация приложений OAuth.

Конечная точка GraphQL

REST API имеет множество конечных точек. С ПОМОЩЬЮ API GraphQL конечная точка остается постоянной, независимо от того, какая операция выполняется. Для , эта конечная точка выглядит:

http(s)://HOSTNAME/api/graphql

Взаимодействие с GraphQL

Поскольку операции GraphQL состоят из многолинейного JSON, GitHub рекомендуется использовать GraphQL Clients для выполнения вызовов GraphQL. Вы также можете использовать curl или любую другую библиотеку HTTP-речи.

В REST HTTP-команды определяют выполняемую операцию. В GraphQL вы предоставите текст в кодировке JSON независимо от того, выполняете ли вы запрос или изменение, поэтому HTTP-команда — POST. Исключение — запрос интроспекционный, который представляет собой простой GET к конечной точке. Для получения дополнительной информации о GraphQL и REST см. Миграция из REST в GraphQL.

Чтобы запросить GraphQL в команде curl , выполните POST запрос с полезными данными JSON. Полезные данные должны содержать строку query:

curl -H "Authorization: bearer TOKEN" -X POST -d " \
 { \
   \"query\": \"query { viewer { login }}\" \
 } \
" http(s)://HOSTNAME/api/graphql

Примечание.

Строковое значение "query" должно экранировать символы новой строки или схема не будет правильно анализировать ее. Для текста запроса POST используйте внешние двойные кавычки и экранированные внутренние двойные кавычки.

Операции запроса и изменения

Два типа разрешённых операций в API GraphQL GitHub — это запросы и мутации. Если сравнивать GraphQL с REST, запросы работают как запросы GET, а изменения — как POST/PATCH/DELETE. Имя мутации определяет, какая модификация будет выполнена.

Сведения об ограничении скорости см. в разделе Ограничения скорости и ограничения запросов для API GraphQL.

Запросы и изменения похожи по форме за несколькими важными различиями.

Сведения о запросах

Запросы GraphQL возвращают только указанные данные. Чтобы сформировать запрос, необходимо указать поля внутри полей (также известных как вложенные подполя), пока не вернёте только скаляры.

Запросы имеют следующую структуру:

query {
  JSON-OBJECT-TO-RETURN
}

Пример реального мира см. в разделе "Пример запроса".

Сведения об изменениях

Чтобы сформировать изменение, необходимо указать три элемента.

  1. Имя изменения — тип нужного изменения.
  2. Входной объект — данные, которые необходимо отправить на сервер; состоят из полей входных данных. Передайте его в качестве аргумента имени изменения.
  3. Объект полезных данных — данные, которые должны быть получены с сервера; состоят из возвращаемых полей. Передайте его в качестве тела имени мутации.

Изменения имеют следующую структуру:

mutation {
  MUTATION-NAME(input: {MUTATION-NAME-INPUT!}) {
    MUTATION-NAME-PAYLOAD
  }
}

Входной объект в этом примере — MutationNameInput, а объект полезных данных — MutationNamePayload.

В ссылке на mutations указаны поля входа — это то, что вы передаёте как объект входа. Кроме того, перечислены возвращаемые поля, передаваемые в качестве объекта полезных данных.

Пример изменения в реальном мире см. в разделе "Пример изменения".

Работа с переменными

Переменные могут сделать запросы более динамичными и эффективными, снизив сложность при передаче входных объектов изменений.

Ниже приведен пример запроса с одной переменной.

query($number_of_repos:Int!) {
  viewer {
    name
     repositories(last: $number_of_repos) {
       nodes {
         name
       }
     }
   }
}
variables {
   "number_of_repos": 3
}

Переменные используются в три этапа.

  1. Определите переменную вне операции в объекте variables:

    variables {
       "number_of_repos": 3
    }
    

    Объект должен быть допустимым кодом JSON. В этом примере показана переменная простого типа Int, но можно определять переменные и более сложных типов, такие как входные объекты. Здесь также можно определить несколько переменных.

  2. Передайте переменную в операцию в качестве аргумента:

    query($number_of_repos:Int!){
    

    Аргумент представляет собой пару "ключ-значение", где ключ — это имя, начинающееся с $ (например, $number_of_repos), а значение — это тип (например, Int). Чтобы указать, что тип является обязательным, добавьте !. Если вы определили несколько переменных, включите их здесь как несколько аргументов.

  3. Используйте переменную в операции:

    repositories(last: $number_of_repos) {
    

    В этом примере переменная означает количество получаемых репозиториев. Тип указывается на шаге 2, так как в GraphQL действует строгая типизация.

Этот процесс делает аргумент запроса динамическим. Теперь мы можем просто изменить значение в объекте variables, оставив остальную часть запроса без изменений.

Использование переменных в качестве аргументов позволяет динамически обновлять значения в объекте variables, не меняя запрос.

Пример запроса

Давайте рассмотрим более сложный запрос в контексте.

Следующий запрос обращается к репозиторию octocat/Hello-World, находит 20 последних закрытых проблем и возвращает заголовок, URL-адрес и первые пять меток каждой проблемы:

query {
  repository(owner:"octocat", name:"Hello-World") {
    issues(last:20, states:CLOSED) {
      edges {
        node {
          title
          url
          labels(first:5) {
            edges {
              node {
                name
              }
            }
          }
        }
      }
    }
  }
}

Рассмотрим его структуру построчно.

  • query {

    Так как мы хотим считать данные с сервера, а не изменить их, query является корневой операцией. (Если операция не указана, query также выполняется по умолчанию.)

  • repository(owner:"octocat", name:"Hello-World") {

    Сначала нужно найти объект repository. Проверка схемы показывает, что для этого объекта требуются аргументы owner и name.

  • issues(last:20, states:CLOSED) {

    Чтобы получить сведения о всех проблемах в репозитории, мы вызываем объект issues. (Мы могли бы запросить одну проблему issue из объекта repository, но для этого нужно знать количество возвращаемых проблем и предоставить его в качестве аргумента.)

    Некоторые сведения об объекте issues:

    • В документации говорится, что этот объект имеет тип IssueConnection.
    • Проверка схемы показывает, что в качестве аргумента для этого объекта требуется количество последних (last) или первых (first) результатов, поэтому мы указываем 20.
    • В документах также говорится, что этот объект принимает states аргумент, который является IssueStateперечислением, OPEN принимаюющим или CLOSED значениями. Чтобы найти только закрытые проблемы, мы присваиваем ключу states значение CLOSED.
  • edges {

    Мы знаем, что объект issues — это соединение, так как он имеет тип IssueConnection. Чтобы получить данные по отдельным проблемам, нужно access узел через edges.

  • node {

    В данном случае мы получаем узлы в конце ребра. В документации по IssueConnection указано, что узел в конце типа IssueConnection является объектом Issue.

  • Теперь, когда мы знаем, что извлекаем объект Issue, мы можем обратиться к документации и указать поля, которые нужно вернуть:

    title
    url
    labels(first:5) {
      edges {
        node {
          name
        }
      }
    }
    

    В данном случае мы указываем поля title, url и labels объекта Issue.

    Тип поля labels — LabelConnection. Как и в случае с объектом issues, так как labels — это соединение, необходимо пройти по его ребрам к подключенному узлу: объекту label. В этом узле можно указать поля объекта label, которые нужно вернуть, в данном случае name.

Вы можете заметить, что выполнение этого запроса в общедоступном Hello-World репозитории Octocat не возвращает много меток. Попробуйте выполнить его в одном из собственных репозиториев, использующих метки, и вы, скорее всего, заметите разницу.

Пример изменения

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

  1. запрос для получения идентификатора проблемы;
  2. изменение для добавления реакции эмодзи на проблему.
query FindIssueID {
  repository(owner:"octocat", name:"Hello-World") {
    issue(number:349) {
      id
    }
  }
}

mutation AddReactionToIssue {
  addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
    reaction {
      content
    }
    subject {
      id
    }
  }
}

Разберем этот пример. Задача звучит просто: добавить реакцию эмодзи на проблему.

С какого же запроса нам начать? Пока мы не знаем.

Так как мы хотим изменить данные на сервере (добавить эмодзи к проблеме), мы начинаем с поиска подходящего изменения в схеме. В справочной документации есть изменение addReaction с таким описанием: Adds a reaction to a subject. Отлично!

В документации по изменению перечислены три поля входных данных:

  • clientMutationId (String)
  • subjectId (ID!)
  • content (ReactionContent!)

Символы ! указывают, что subjectId и content являются обязательными полями. То, что поле content обязательное, разумно: мы хотим добавить реакцию, поэтому нам нужно указать, какой эмодзи следует использовать.

Но почему обязательным является поле subjectId? Это связано с тем, что subjectId — это единственный способ указать, на какую проблему в каком репозитории следует отреагировать.

Вот почему мы начинаем этот пример с запроса: чтобы получить ID.

Давайте разберем запрос построчно.

  • query FindIssueID {

    Здесь мы выполняем запрос и называем его FindIssueID. Обратите внимание, что именование запроса является необязательным; мы даем ему имя здесь, чтобы мы могли включить его в то же окно клиента графического интерфейса, что и мутация.

  • repository(owner:"octocat", name:"Hello-World") {

    Мы указываем репозиторий, запрашивая объект repository и передавая аргументы owner и name.

  • issue(number:349) {

    Мы указываем проблему, на которую нужно отреагировать, запрашивая объект issue и передавая аргумент number.

  • id

    Здесь мы получаем id``https://github.com/octocat/Hello-World/issues/349, чтобы пройти за subjectId.

При выполнении запроса мы получаем id``MDU6SXNzdWUyMzEzOTE1NTE=.

Примечание.

Возвращаемое id в запросе значение, которое мы передадим в виде subjectID изменения. Ни в документации, ни в схеме эта связь не определена. Необходимо просто понимать, как работают имена.

Зная идентификатор, мы можем перейти к изменению:

  • mutation AddReactionToIssue {

    Здесь мы выполняем изменение и называем его AddReactionToIssue. Как и в случае с запросами, именование мутации является необязательным; мы даем ему имя здесь, чтобы мы могли включить его в то же окно клиента с графическим интерфейсом, что и запрос.

  • addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {

    Разберем эту строку:

    • addReaction — это имя изменения.
    • input — это обязательный ключ аргумента. Для изменения это всегда input.
    • {subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY} — это обязательное значение аргумента. Это всегда будет входной объект (отсюда и завитые скобки), состоящий из входных полей (subjectId и content в данном случае) для мутации.

    Как узнать, какое значение следует использовать для содержимого? ВaddReaction документации говорится, что в content поле есть тип ReactionContent, который является enum, потому что в GitHub поддерживаются только определённые эмодзи-реакции. Ниже перечислены допустимые значения для реакций (обратите внимание, что некоторые значения отличаются от соответствующих имен эмодзи).

    СодержимоеЭмодзи
    +1👍
    -1👎
    laugh😄
    confused😕
    heart❤️
    hooray🎉
    rocket🚀
    eyes👀
  • Остальная часть вызова — это объект полезных данных. Здесь мы указываем данные, которые сервер должен вернуть после изменения. В документации по addReaction определены три возможных возвращаемых поля:

    • clientMutationId (String)
    • reaction (Reaction!)
    • subject (Reactable!)

    В этом примере возвращаются два обязательных поля (reaction и subject); оба они имеют обязательные вложенные поля (content и id соответственно).

При выполнении изменения ответ будет следующим:

{
  "data": {
    "addReaction": {
      "reaction": {
        "content": "HOORAY"
      },
      "subject": {
        "id": "MDU6SXNzdWUyMTc5NTQ0OTc="
      }
    }
  }
}

Вот и все! Проверьте свою reaction на проблему наведя курсор на 🎉 чтобы найти своё имя пользователя.

Последнее замечание: при передаче нескольких полей во входном объекте синтаксис может получиться громоздким. Помочь может помещение полей в переменную. Вот как можно переписать исходное изменение с использованием переменной:

mutation($myVar:AddReactionInput!) {
  addReaction(input:$myVar) {
    reaction {
      content
    }
    subject {
      id
    }
  }
}
variables {
  "myVar": {
    "subjectId":"MDU6SXNzdWUyMTc5NTQ0OTc=",
    "content":"HOORAY"
  }
}

Примечание.

Вы можете заметить, что в значении поля content в предыдущем примере (где оно используется в изменении напрямую) нет кавычек вокруг HOORAY, но при использовании в переменной кавычки есть. Этому есть причина:

  • При использовании content в изменении напрямую схема предполагает, что значение имеет тип ReactionContent, который является перечислением, а не строкой. Если добавить кавычки вокруг значения перечисления, при проверке схемы возникнет ошибка, так как кавычки зарезервированы для строк.
  • При использовании content в переменной раздел переменных должен быть допустимым кодом JSON, поэтому кавычки требуются. Проверка схемы правильно интерпретирует тип ReactionContent, когда переменная передается в изменение во время выполнения.

Дополнительные сведения о различиях между перечислениями и строками см. в официальной спецификации GraphQL.

Дополнительные материалы

При формировании вызовов GraphQL доступно гораздо больше возможностей. Дополнительную информацию можно найти в следующих ресурсах: