Skip to main content

Verwenden der Paginierung in der REST-API

Hier erfährst du, wie du über die REST-API durch paginierte Antworten navigierst.

Informationen zur Paginierung

Wenn eine Antwort der REST-API viele Ergebnisse enthält, wird GitHub die Ergebnisse aufteilen, und eine Teilmenge dieser wird zurückgegeben. gibt beispielsweise nur 30 Issues aus dem Repository zurück, obwohl das Repository über 1600 offene Issues enthält. Dadurch werden die Antworten für Server und Benutzer*innen leichter zu bewältigen.

Du kannst den -Header aus der Antwort verwenden, um zusätzliche Datenseiten anzufordern. Wenn ein Endpunkt den Abfrageparameter unterstützt, kannst du steuern, wie viele Ergebnisse auf einer Seite zurückgegeben werden.

In diesem Artikel wird veranschaulicht, wie du zusätzliche Ergebnisseiten für paginierte Antworten anforderst, die Anzahl der auf jeder Seite zurückgegebenen Ergebnisse änderst und ein Skript schreibst, um mehrere Ergebnisseiten abzurufen.

Wenn die Antwort paginiert ist, enthält der Antwort-Header einen Header. Der -Header wird weggelassen, wenn der Endpunkt keine Paginierung unterstützt oder alle Ergebnisse auf eine einzelne Seite passen.

Der -Header enthält URLs, mit denen du zusätzliche Ergebnisseiten abrufen kannst. Beispielsweise die vorherige, nächste, erste und letzte Seite der Ergebnisse.

Um die Antwortheader für einen bestimmten Endpunkt anzuzeigen, können Sie curl, GitHub CLI oder eine Bibliothek verwenden, die Sie zum Senden von Anforderungen verwenden. Um die Antwortheader anzuzeigen, wenn du eine Bibliothek zum Senden von Anforderungen verwendest, befolge die Anweisungen in der Dokumentation für diese Bibliothek. Um die Antwortheader anzuzeigen, wenn Sie curl oder GitHub CLI verwenden, übergeben Sie das Flag --include mit Ihrer Anforderung. Zum Beispiel:

curl --include --request GET \
--url "https://api.github.com/repos/octocat/Spoon-Knife/issues" \
--header "Accept: application/vnd.github+json"

Wenn die Antwort paginiert ist, sieht der -Header ungefähr wie folgt aus:

link: <https://api.github.com/repositories/1300192/issues?page=2>; rel="prev", <https://api.github.com/repositories/1300192/issues?page=4>; rel="next", <https://api.github.com/repositories/1300192/issues?page=515>; rel="last", <https://api.github.com/repositories/1300192/issues?page=1>; rel="first"

Der -Header enthält die URL für die vorherige, nächste, erste und letzte Ergebnisseite:

  • Die URL für die vorherige Seite wird gefolgt von .
  • Die URL für die nächste Seite wird gefolgt von .
  • Die URL für die letzte Seite wird gefolgt von .
  • Die URL für die erste Seite wird gefolgt von .

In einigen Fällen ist nur eine Teilmenge dieser Links verfügbar. Beispielsweise ist der Link zur vorherigen Seite nicht enthalten, wenn du dich auf der ersten Ergebnisseite befindest, und der Link zur letzten Seite ist nicht enthalten, wenn er nicht berechnet werden kann.

Du kannst die URLs aus dem -Header verwenden, um eine weitere Ergebnisseite anzufordern. So forderst du beispielsweise die letzte Ergebnisseite basierend auf dem vorherigen Beispiel an:

curl --include --request GET \
--url "https://api.github.com/repositories/1300192/issues?page=515" \
--header "Accept: application/vnd.github+json"

Die URLs im -Header verwenden Abfrageparameter, um anzugeben, welche Ergebnisseite zurückgegeben werden soll. Die Abfrageparameter in den -URLs können sich je nach Endpunkt unterscheiden: Jeder paginierte Endpunkt verwendet die Abfrageparameter , , oder . (Einige Endpunkte verwenden den Parameter für andere Zwecke als die Paginierung.) In allen Fällen kannst du die URLs im -Header verwenden, um zusätzliche Ergebnisseiten abzurufen. Weitere Informationen zu Abfrageparametern findest du unter AUTOTITLE.

Ändern der Anzahl der Elemente pro Seite

Wenn ein Endpunkt den Abfrageparameter unterstützt, kannst du steuern, wie viele Ergebnisse auf einer Seite zurückgegeben werden. Weitere Informationen zu Abfrageparametern findest du unter AUTOTITLE.

Diese Anforderung verwendet beispielsweise den Abfrageparameter , um zwei Elemente pro Seite zurückzugeben:

curl --include --request GET \
--url "https://api.github.com/repos/octocat/Spoon-Knife/issues?per_page=2" \
--header "Accept: application/vnd.github+json"

Der Parameter wird automatisch in den -Header eingeschlossen. Zum Beispiel:

link: <https://api.github.com/repositories/1300192/issues?per_page=2&page=2>; rel="next", <https://api.github.com/repositories/1300192/issues?per_page=2&page=7715>; rel="last"

Skriptprogrammierung mit Paginierung

Anstatt URLs manuell aus dem -Header zu kopieren, kannst du ein Skript schreiben, um mehrere Ergebnisseiten abzurufen.

In den folgenden Beispielen werden JavaScript und die Octokit.js-Bibliothek von GitHub verwendet. Weitere Informationen zu Octokit.js findest du unter AUTOTITLE und in der Infodatei Octokit.js.

Beispiel für die Verwendung der Octokit.js-Paginierungsmethode

Sie können eine Methode verwenden, um mit Octokit.js paginierte Ergebnisse abzurufen. ruft die nächste Ergebnisseite ab, bis die letzte Seite erreicht ist, und gibt dann alle Ergebnisse als einzelnes Array zurück. Einige Endpunkte geben paginierte Ergebnisse als Array in einem Objekt zurück, anstatt die paginierten Ergebnisse als Array zurückzugeben. gibt immer ein Array aus Elementen zurück, auch wenn das Rohergebnis ein Objekt war.

Dieses Skript ruft beispielsweise alle Issues aus dem Repository ab. Obwohl 100 Issues gleichzeitig angefordert werden, wird die Funktion erst zurückgegeben, wenn die letzte Datenseite erreicht ist.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ });

const data = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "octocat",
  repo: "Spoon-Knife",
  per_page: 100,
  headers: {
    "X-GitHub-Api-Version": "2022-11-28",
  },
});

console.log(data)

Du kannst eine optionale Zuordnungsfunktion übergeben, um die Seitennummerierung zu beenden, bevor die letzte Seite erreicht wird, oder um die Arbeitsspeicherauslastung zu reduzieren, indem nur eine Teilmenge der Rückmeldung behalten wird. Du kannst auch verwenden, um immer nur eine Seite gleichzeitig zu durchlaufen, anstatt jede Seite anzufordern. Weitere Informationen findest du in der Octokit.js-Dokumentation.

Beispiel zum Erstellen einer Paginierungsmethode

Wenn du eine andere Sprache oder Bibliothek ohne Paginierungsmethode verwendest, kannst du eine eigene Paginierungsmethode erstellen. In diesem Beispiel wird weiterhin die Octokit.js-Bibliothek verwendet, um Anforderungen zu stellen, doch es besteht keine Abhängigkeit von .

Die Funktion sendet eine Anforderung an einen Endpunkt. Die Daten aus der Antwort werden von verarbeitet. Mit dieser Funktion werden Fälle verarbeitet, in denen keine Daten zurückgegeben werden oder die zurückgegebenen Daten ein Objekt anstelle eines Arrays sind. Die verarbeiteten Daten werden dann an eine Liste angefügt, die alle bisher gesammelten paginierten Daten enthält. Wenn die Antwort einen -Header enthält und der -Header einen Link für die nächste Seite enthält, verwendet die Funktion ein RegEx-Muster (), um die URL für die nächste Seite abzurufen. Die Funktion wiederholt dann die vorherigen Schritte und verwendet nun diese neue URL. Sobald der -Header keinen Link zur nächsten Seite mehr enthält, werden alle Ergebnisse zurückgegeben.

JavaScript
import { Octokit } from "octokit";

const octokit = new Octokit({ });

async function getPaginatedData(url) {
  const nextPattern = /(?<=<)([\S]*)(?=>; rel="next")/i;
  let pagesRemaining = true;
  let data = [];

  while (pagesRemaining) {
    const response = await octokit.request(`GET ${url}`, {
      per_page: 100,
      headers: {
        "X-GitHub-Api-Version":
          "2022-11-28",
      },
    });

    const parsedData = parseData(response.data)
    data = [...data, ...parsedData];

    const linkHeader = response.headers.link;

    pagesRemaining = linkHeader && linkHeader.includes(`rel=\"next\"`);

    if (pagesRemaining) {
      url = linkHeader.match(nextPattern)[0];
    }
  }

  return data;
}

function parseData(data) {
  // If the data is an array, return that
    if (Array.isArray(data)) {
      return data
    }

  // Some endpoints respond with 204 No Content instead of empty array
  //   when there is no data. In that case, return an empty array.
  if (!data) {
    return []
  }

  // Otherwise, the array of items that we want is in an object
  // Delete keys that don't include the array of items
  delete data.incomplete_results;
  delete data.repository_selection;
  delete data.total_count;
  // Pull out the array of items
  const namespaceKey = Object.keys(data)[0];
  data = data[namespaceKey];

  return data;
}

const data = await getPaginatedData("/repos/octocat/Spoon-Knife/issues");

console.log(data);