GitHub-REST-API-Delphi-Client mit sgcOpenAPI

GitHub pflegt eine der größten OpenAPI-Beschreibungen, die überhaupt veröffentlicht werden, und gibt sie unter der MIT-Lizenz frei. sgcOpenAPI liefert keine handgeschriebene GitHub-Komponente mit, sondern einen Generator. Ein einziger Kommandozeilenaufruf über api.github.com.json erzeugt eine einzige Pascal-Unit mit 1.225 Methoden, einer typisierten Response-Klasse für jede davon und einer Funktion GetOpenAPIClient, die dir einen fertigen Client liefert.

GitHub + sgcOpenAPI

Die Zahlen weiter unten sind nicht geschätzt, sondern gemessen: der Generator lief über die aktuelle Beschreibung und das Ergebnis wurde kompiliert.

Quell-Spezifikation

descriptions/api.github.com/api.github.com.json in github/rest-api-description, deklariert als OpenAPI 3.0.3. Ein Konvertierungsschritt ist nicht nötig.

Was dabei herauskommt

Aus 813 Pfaden werden 1.225 Methoden und 1.134 Response-Klassen, dazu 3.250 Modellklassen, in einer einzigen Unit von rund 274.000 Zeilen.

Authentifizierung

Generiere mit -a 2 und setze zur Laufzeit Authentication.Token.BearerToken. Das deckt einen Personal Access Token genauso ab wie einen Installation Token.

Kompiliert sauber

Die generierte Unit baut sauber unter RAD Studio 12 für Win32, mit nichts im Bibliothekspfad außer dem Source-Ordner von sgcOpenAPI.

Den Generator ausführen

GitHub veröffentlicht mehrere Spielarten derselben Beschreibung. api.github.com.json beschreibt den gehosteten Dienst, ghes-3.x.json beschreibt GitHub Enterprise Server. Generiere aus derjenigen, auf die du zielst.

> sgcOpenAPI.exe -i "api.github.com.json" -o "github.pas" -a 2

File successfully created github.pas

-i nimmt eine lokale Datei oder eine URL und akzeptiert JSON wie YAML. -o ist die zu schreibende Pascal-Unit, und die Unit wird nach dieser Datei benannt. -a 2 wählt die Token-Authentifizierung, jede generierte Methode sendet also Authorization: Bearer. Dieselbe ausführbare Datei ist ein GUI-Assistent, wenn du sie ohne Parameter startest, und sie endet mit 0 bei Erfolg, mit 5 bei einer fehlerhaften Eingabedatei, mit 6 bei einer fehlerhaften Ausgabedatei und mit 7, wenn sich das Dokument nicht in ein gültiges OpenAPI-3-Dokument überführen lässt.

Nimm die generierte .pas ins Projekt auf und trag sie in eine uses-Klausel ein. Es gibt keine Komponente zu installieren, denn sgcOpenAPI registriert keine und liefert kein Design-Time-Package mit.

Deine Repositories auflisten

GitHub schreibt seine Operation-IDs mit Schrägstrichen und Bindestrichen, etwa repos/list-for-authenticated-user. Diese Zeichen dürfen in einem Pascal-Bezeichner nicht vorkommen, der Generator entfernt sie also, und die Methode heißt am Ende reposlistforauthenticateduser.

uses
  github;   // die gerade generierte Unit

procedure TfrmGitHub.btnReposClick(Sender: TObject);
var
  oResponse: TsgcOpenAPI_reposlistforauthenticateduser_Response;
  oRepo: TsgcOpenAPI_repository_Class;
begin
  GetOpenAPIClient.Authentication.Token.BearerToken := txtToken.Text;

  oResponse := GetOpenAPIClient.reposlistforauthenticateduser(
    'private', 'owner', 'all', 'full_name', '', 100, 1);
  try
    if oResponse.IsSuccessful then
    begin
      for oRepo in oResponse.Successful.Items do
        memoLog.Lines.Add(oRepo.Full_name + '  ' + oRepo.Description);
    end
    else
      memoLog.Lines.Add(IntToStr(oResponse.ResponseCode) + ' ' +
        oResponse.ResponseError);
  finally
    oResponse.Free;
  end;
end;

Ein Endpunkt, der ein Array zurückgibt, bekommt eine Antwort, deren Successful ein TsgcOpenAPIArray-Nachfahre mit typisiertem Items ist, hier TArray<TsgcOpenAPI_repository_Class>. Die Basis-URL stammt aus dem servers-Eintrag, der generierte Konstruktor setzt also bereits https://api.github.com. Die Paginierung wird nicht vor dir versteckt: aPer_page und aPage sind gewöhnliche Argumente, und du läufst selbst über die Seiten.

Wenn dich die kleingeschriebenen Namen stören, generiere mit -m 1, dann werden die Methoden nach der Zusammenfassung der Operation benannt, oder mit -m 2, dann nach dem Endpunkt.

Ein Issue anlegen und Pull Requests auflisten

Pfadparameter kommen als führende Argumente an, in der Reihenfolge, in der das Dokument sie deklariert. Der Request-Body kommt als String an, aus dem Grund, der weiter unten steht.

var
  oIssue: TsgcOpenAPI_issuescreate_Response;
  oPulls: TsgcOpenAPI_pullslist_Response;
begin
  oIssue := GetOpenAPIClient.issuescreate('octocat', 'Hello-World',
    '{"title":"Memory leak in the HTTP/2 reader",' +
    '"body":"Repro steps: ...","labels":["bug","http2"]}');
  try
    if oIssue.IsSuccessful then
      memoLog.Lines.Add('filed issue #' +
        IntToStr(oIssue.Successful.Number) + ' ' + oIssue.Successful.Html_url)
    else
      memoLog.Lines.Add(oIssue.Error422._message);
  finally
    oIssue.Free;
  end;

  oPulls := GetOpenAPIClient.pullslist('octocat', 'Hello-World',
    'open', 'updated');
  try
    memoLog.Lines.Add(IntToStr(oPulls.ResponseCode));
  finally
    oPulls.Free;
  end;
end;

Jede Response-Klasse trägt Successful plus eine Eigenschaft pro Statuscode, den das Dokument deklariert. Error304, Error401, Error403 und Error422 stehen also zum Auslesen bereit, wenn der Aufruf fehlschlägt. Ein Status, den GitHub mit einem benannten Schema beschreibt, wird zu einer Klasse, und einer, den GitHub mit gar nichts beschreibt, wird zu einem einfachen String. Die Fehler-Eigenschaft wird bei Bedarf erzeugt, ist also nie nil, und du prüfst IsSuccessful statt das Objekt zu testen.

Der Unterstrich in _message ist kein Tippfehler. message ist eines der 68 reservierten Pascal-Wörter, die der Generator maskiert, ein Schemafeld mit diesem Namen kommt also mit führendem Unterstrich an. Dasselbe passiert mit type, object, default, index und dem Rest der Liste, die alle irgendwo in GitHubs Schemas vorkommen.

Was die generierte Unit enthält

Die Unit spiegelt die Beschreibung. Nichts wird kuratiert, alles was GitHub dokumentiert ist also da, und alles was GitHub auslässt fehlt.

Jede dokumentierte Operation

1.225 Methoden, für Repositories und Contents, Issues und Pull Requests, Actions und Check Runs, Packages, Organisationen und Teams, GitHub Apps, Code Scanning und den Rest der Oberfläche.

Eine Response-Klasse pro Methode

Jede stammt von TsgcOpenAPIResponse ab und erbt IsSuccessful, das bei 200 bis 299 wahr ist, dazu ResponseCode und ResponseError.

3.250 Modellklassen

TsgcOpenAPI_repository_Class, TsgcOpenAPI_issue_Class, TsgcOpenAPI_basic_error_Class, TsgcOpenAPI_validation_error_Class und jedes andere Schema aus dem components-Abschnitt.

Tags als Kommentare

GitHubs Tags werden als Kommentare ausgegeben, die die Methoden innerhalb der einen Client-Klasse gruppieren. Zu eigenen Klassen werden sie nicht, alles hängt also an GetOpenAPIClient.

Die Dokumentation aus der Spezifikation

GitHubs eigene Beschreibungen kommen als Pascal-Kommentare über jeder Methode und jeder Eigenschaft an, die IDE zeigt sie also genau dort, wo du sie verwendest.

Enterprise Server ebenfalls

Die ghes-3.x-Beschreibungen generieren genauso. Halte eine generierte Unit pro Ziel vor, wenn du mit beiden sprichst.

Vier Dinge, die du wissen solltest

Alle vier stammen aus einem echten Generierungslauf über die aktuelle Beschreibung.

Die Unit ist sehr groß

Rund 274.000 Zeilen und 12 MB, die größte der öffentlichen Spezifikationen, die wir hier generieren. Das Kompilieren dauert unter zwei Sekunden, aber der Editor der IDE wird bei einer Datei dieser Größe langsam. -x lässt Operationen weg, die du als "VERB endpoint" aufführst, und -p entfernt danach die Klassen, die keine verbliebene Operation mehr nutzt.

Die meisten Request-Bodies sind Strings

343 Operationen deklarieren einen application/json-Body, aber fast alle beschreiben ihn als anonymes Inline-Objekt statt als benanntes Schema. Ein Inline-Objekt hat keinen Namen, den eine Klasse tragen könnte, der Parameter lautet deshalb const aBody: string und du baust das JSON selbst. Die wenigen, die ein benanntes Schema referenzieren, bekommen sehr wohl eine typisierte Klasse.

273 Warnungen, und sie lohnen die Lektüre

Die meisten betreffen Composition ohne Discriminator-Mapping, wobei die generierte Klasse ein Member pro Zweig trägt. Ein paar melden ein $ref, das im Dokument nicht auflösbar ist, und ein paar melden eine Operation mit zwei Erfolgsstatus, von denen nur einer generiert wird. Der Generator sagt welcher, statt still zu wählen.

Rate Limits und App-Tokens liegen bei dir

Der generierte Client ist ein getreuer HTTP-Client und nicht mehr. Er cacht keine ETag-Werte, wiederholt nichts bei 403 und erneuert keinen Installation Token einer GitHub App. Lies ResponseCode aus, setze über OnBeforeRequest einen Conditional-Request-Header, und erzeuge Installation Tokens mit den apps-Methoden, die die Unit bereits enthält.

Aus dem Blog

OpenAPI-Delphi-Parser

Wie der Parser reale Spezifikationen handhabt, einschließlich der Composition-Keywords hinter den meisten Warnungen.

Beitrag lesen →

OpenAPI-Client und -Parser

Der Begleitbeitrag, der den generierten Client vorstellt und den Parser, auf dem er aufsetzt.

Beitrag lesen →

sgcOpenAPI 2026.6

Release Notes zur aktuellen Version, mit den Generator-Optionen und den Änderungen am Parser.

Beitrag lesen →
Bestes Preis-Leistungs-Verhältnis: All-AccessAlle eSeGeCe-Produkte, inklusive Premium-Support, ab €1,059 pro Jahr.
All-Access-Preise ansehen

Baue deine GitHub-Automatisierung noch heute

sgcOpenAPI liefert den Parser, den Codegenerator, den OpenAPI-Server und fertige SDKs für Amazon, Azure, Google und Microsoft mit. Ein Produkt, drei Stufen, nach Arbeitsplatz statt nach Funktionsumfang bepreist.