Skip to main content

Migrieren von REST zu GraphQL

Hier lernst du Best Practices und Überlegungen zur Migration von der GitHub-REST API zur GitHub-GraphQL-API kennen.

Unterschiede in der API-Logik

Beim Migrieren von REST zu GraphQL ändert sich die API-Logik drastisch. Die Unterschiede zwischen REST als Stil und GraphQL als Spezifikation gestalten es oft schwierig (und lästig), REST-API-Aufrufe eins zu eins durch GraphQL-API-Abfragen zu ersetzen. Unten findest du spezifische Beispiele für die Migration.

So migrierst du deinen Code aus der REST-API zur GraphQL-API:

Folgendes gehört zu den wichtigsten Vorteilen von GraphQL:

Im Folgenden findest du Beispiele zu jedem Vorteil.

Beispiel: Nur benötigte Daten werden abgerufen

Ein einzelner REST-API-Aufruf ruft eine Liste der Mitglieder deiner Organisation ab:

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

Wenn du nur Namen von Mitgliedern und Links zu Avataren abrufen möchtest, enthalten die REST-Nutzdaten eine zu große Datenmenge. Eine GraphQL-Abfrage gibt jedoch nur das zurück, was du angibst:

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

Weiteres Beispiel: Du rufst eine Liste von Pull Requests ab und überprüfst, ob alle gemergt werden können. Ein Aufruf der REST-API ruft eine Liste der Pull Requests und deren Zusammenfassungsdarstellungen ab:

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

Wenn du bestimmen möchtest, ob ein Pull Request zusammengeführt werden kann, muss jeder Pull Request aufgrund der detaillierten Darstellung (vieler Nutzdaten) einzeln abgerufen werden, und du musst überprüfen, ob das mergeable-Attribut TRUE oder FALSE ist.

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

Mit GraphQL kannst du nur die number- und mergeable-Attribute jedes Pull Requests abrufen:

query {
    repository(owner:"octocat", name:"Hello-World") {
    pullRequests(last: 10) {
      edges {
        node {
          number
          mergeable
        }
      }
    }
  }
}

Beispiel: Schachtelung

Bei Abfragen mit geschachtelten Felder kannst du anstelle von mehreren REST-Aufrufen weniger GraphQL-Abfragen verwenden. Beispielsweise erfordert das Abrufen eines Pull Requests mit den Commits, nicht überprüften Kommentaren und Reviews mithilfe der REST-API vier separate Aufrufe:

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

Mit der GraphQL-API kannst du die Daten bei Verwendung geschalteter Felder mit einer einzelnen Abfrage abrufen:

{
  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
          }
        }
      }
    }
  }
}

Du kannst die Leistung dieser Abfrage außerdem verbessern, indem du eine Variable durch die Nummer des Pull Requests ersetzt.

Beispiel: Starke Typbindung

GraphQL-Schemas weisen eine starke Typbindung auf, wodurch der Umgang mit Daten sicherer wird.

Stelle dir vor, dass du mithilfe einer GraphQL-Mutation einen Kommentar zu einem Issue oder Pull Request hinzufügst und versehentlich eine ganze Zahl anstelle einer Zeichenfolge für den Wert von clientMutationId angibst:

mutation {
  addComment(input:{clientMutationId: 1234, subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}

Die Ausführung dieser Abfrage gibt Fehler zurück, die angeben, welche Typen bei dem Vorgang erwartet werden:

{
  "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
        }
      ]
    }
  ]
}

Wenn du 1234 mit Anführungszeichen umschließt, wird der Wert von einer ganzen Zahl in eine Zeichenfolge (den erwarteten Typ) umgewandelt:

mutation {
  addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}