Google Cloud Storage über gRPC in Delphi

· Komponenten

Google Cloud Storage ist der Objektspeicherdienst von Google. Daten liegen in Buckets, und jeder Bucket enthält Objekte (Dateien), die Sie hochladen, auflisten, lesen und löschen. Der meiste Delphi-Code erreicht ihn über die JSON-REST-API, aber der Storage-Dienst stellt auch eine gRPC-API bereit, die Protocol Buffers über HTTP/2 spricht. sgcWebSockets Enterprise liefert einen typisierten Cloud-Storage-gRPC-Client auf Basis von TsgcGRPCClient, sodass Sie Buckets und Objekte aus Delphi und C++Builder steuern können, ohne externe Laufzeitumgebung oder generierte Stubs.

Wie es funktioniert

Die gRPC-Storage-API befindet sich unter storage.googleapis.com:443 und spricht den Dienst google.storage.v2.Storage. sgcWebSockets liefert bereits einen vollständigen HTTP/2-Stack, sodass der typisierte Client auf einem TsgcHTTP2Client-Transport mit aktiviertem TLS aufsetzt. TsgcGRPCClient übernimmt das gRPC-Framing, die Header und die Timeout-Behandlung, öffnet den HTTP/2-Stream und parst die Response und die Trailer zurück in ein TsgcGRPCResponse.

Die typisierte Schicht befindet sich in der Unit sgcGRPC_Google_Storage. Sie gibt Ihnen Request- und Response-Klassen wie TsgcGRPCStorageListBucketsRequest, TsgcGRPCStorageListObjectsResponse und TsgcGRPCStorageBucket, die sich selbst zu und von Protocol Buffers serialisieren. Sie setzen typisierte Eigenschaften, rufen ToBytes auf, um die Request-Nutzdaten zu erhalten, senden sie mit Call und laden die Antwort mit LoadFromBytes. Kein Protobuf-Compiler, keine handgeschriebenen Feld-Tags.

Die Authentifizierung verwendet ein Google-Dienstkonto. Der Client signiert einen JSON Web Token aus dem Dienstkonto-Schlüssel und präsentiert ihn als Bearer-Token in den gRPC-authorization-Metadaten, was die standardmäßige Art ist, wie Google Cloud Server-zu-Server-Aufrufe autorisiert.

Den Transport einrichten

Ein gRPC-Channel ist einfach eine HTTP/2-Verbindung. Richten Sie einen TsgcHTTP2Client mit aktiviertem TLS auf den Storage-Endpunkt, hängen Sie ihn dann an TsgcGRPCClient an und wählen Sie den binären Protocol-Buffers-Content-Type.

uses
  sgcHTTP2_Client, sgcGRPC_Client, sgcGRPC_Types, sgcGRPC_Google_Storage;

var
  HTTP2: TsgcHTTP2Client;
  GRPC: TsgcGRPCClient;
begin
  HTTP2 := TsgcHTTP2Client.Create(nil);
  HTTP2.Host := 'storage.googleapis.com';
  HTTP2.Port := 443;
  HTTP2.TLS  := True;

  GRPC := TsgcGRPCClient.Create(nil);
  GRPC.Client := HTTP2;
  GRPC.ChannelOptions.ContentType := grpcProto;
  GRPC.ChannelOptions.Compression := grpcNoCompression;

  HTTP2.Active := True;
end;

Authentifizierung mit einem Dienstkonto

Laden Sie den Dienstkonto-JSON-Schlüssel, konfigurieren Sie ein für den Storage-Endpunkt signiertes JWT und legen Sie das resultierende Token in DefaultMetadata ab, sodass es bei jedem Aufruf mitgesendet wird. Das selbstsignierte Dienstkonto-JWT ist audience-gebunden, daher muss API_Endpoint auf storage.googleapis.com verweisen, damit das Token akzeptiert wird.

var
  Cloud: TsgcHTTPGoogleCloud_PubSub_Client;
begin
  Cloud := TsgcHTTPGoogleCloud_PubSub_Client.Create(nil);
  Cloud.LoadSettingsFromFile('service-account.json');
  Cloud.GoogleCloudOptions.Authentication := gcaJWT;
  Cloud.GoogleCloudOptions.JWT.API_Endpoint := 'https://storage.googleapis.com/';

  // OnAuthToken fires when the token is ready; copy it into the gRPC metadata
  GRPC.DefaultMetadata.Clear;
  GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);
end;

Buckets auflisten

Um die Buckets in einem Projekt aufzuzählen, füllen Sie einen TsgcGRPCStorageListBucketsRequest mit dem Projekt als Parent, serialisieren ihn und führen einen unären Call zur Methode ListBuckets aus. Die Antwort-Bytes laden direkt in ein TsgcGRPCStorageListBucketsResponse, das jeden Bucket mit seinem Namen und Standort bereitstellt.

var
  oRequest: TsgcGRPCStorageListBucketsRequest;
  oResponse: TsgcGRPCResponse;
  oBuckets: TsgcGRPCStorageListBucketsResponse;
  i: Integer;
begin
  oRequest := TsgcGRPCStorageListBucketsRequest.Create;
  try
    oRequest.Parent := 'projects/' + ProjectId;
    oRequest.PageSize := 100;

    oResponse := GRPC.Call('google.storage.v2.Storage', 'ListBuckets',
      oRequest.ToBytes);
  finally
    oRequest.Free;
  end;

  if oResponse.StatusCode = grpcOK then
  begin
    oBuckets := TsgcGRPCStorageListBucketsResponse.Create;
    try
      oBuckets.LoadFromBytes(oResponse.Data);
      for i := 0 to oBuckets.BucketCount - 1 do
        Memo1.Lines.Add(oBuckets.Bucket(i).Name + ' (location: ' +
          oBuckets.Bucket(i).Location + ')');
    finally
      oBuckets.Free;
    end;
  end;
end;

Einen Bucket erstellen

Das Erstellen eines Buckets folgt demselben Muster mit TsgcGRPCStorageCreateBucketRequest. Setzen Sie das Parent-Projekt, die neue Bucket-ID und das Projekt, dem die Bucket-Ressource gehört, und rufen Sie dann CreateBucket auf. Die Response trägt den erstellten TsgcGRPCStorageBucket.

var
  oRequest: TsgcGRPCStorageCreateBucketRequest;
  oResponse: TsgcGRPCResponse;
begin
  oRequest := TsgcGRPCStorageCreateBucketRequest.Create;
  try
    oRequest.Parent := 'projects/' + ProjectId;
    oRequest.BucketId := 'my-new-bucket';
    oRequest.Bucket.Project := 'projects/' + ProjectId;

    oResponse := GRPC.Call('google.storage.v2.Storage', 'CreateBucket',
      oRequest.ToBytes);
  finally
    oRequest.Free;
  end;
end;

Objekte in einem Bucket auflisten

Das Auflisten der Objekte in einem Bucket verwendet TsgcGRPCStorageListObjectsRequest. Der Parent ist der Bucket-Ressourcenname in der Form projects/_/buckets/<bucket>. Die Response gibt Ihnen den Namen, die Größe und den Content-Type jedes Objekts, und Sie können optional Prefix und Delimiter setzen, um eine ordnerartige Hierarchie zu durchlaufen.

var
  oRequest: TsgcGRPCStorageListObjectsRequest;
  oResponse: TsgcGRPCResponse;
  oObjects: TsgcGRPCStorageListObjectsResponse;
  i: Integer;
begin
  oRequest := TsgcGRPCStorageListObjectsRequest.Create;
  try
    oRequest.Parent := 'projects/_/buckets/' + BucketName;
    oRequest.PageSize := 100;

    oResponse := GRPC.Call('google.storage.v2.Storage', 'ListObjects',
      oRequest.ToBytes);
  finally
    oRequest.Free;
  end;

  if oResponse.StatusCode = grpcOK then
  begin
    oObjects := TsgcGRPCStorageListObjectsResponse.Create;
    try
      oObjects.LoadFromBytes(oResponse.Data);
      for i := 0 to oObjects.ObjectCount - 1 do
        Memo1.Lines.Add(oObjects.Object_(i).Name + ' (size: ' +
          IntToStr(oObjects.Object_(i).Size) + ', type: ' +
          oObjects.Object_(i).ContentType + ')');
    finally
      oObjects.Free;
    end;
  end;
end;

Objektdaten lesen und schreiben

Über die Bucket- und Objekt-Metadaten hinaus deckt die Unit auch Objekt-Nutzdaten ab. TsgcGRPCStorageReadObjectRequest liest Bytes aus einem Objekt zurück, mit optionalem ReadOffset und ReadLimit für bereichsbezogene Downloads, und die passende Response stellt die rohen Data-Bytes bereit. TsgcGRPCStorageWriteObjectRequest lädt Objektinhalt in Chunks hoch: Setzen Sie die WriteObjectSpec-Ressource für den ersten Chunk, schieben Sie Data bei steigenden WriteOffset-Werten und markieren Sie FinishWrite beim letzten Chunk. Da jede Nachricht über ToBytes und LoadFromBytes serialisiert wird, funktionieren dieselben typisierten Klassen, egal ob Sie eine kleine Datei in einem Aufruf hochladen oder ein großes Objekt in Teilen streamen.

Pagination und Fehlerbehandlung

Die Listen-Responses geben einen NextPageToken zurück, wenn weitere Ergebnisse verfügbar sind. Kopieren Sie ihn in das PageToken des nächsten Requests und rufen Sie erneut auf, um durch große Buckets oder lange Objektlisten zu blättern. Auf der Fehlerseite trägt jedes TsgcGRPCResponse einen typisierten StatusCode, sodass ein Nicht-grpcOK-Ergebnis Ihnen genau sagt, was schiefgelaufen ist, von grpcUNAUTHENTICATED für ein fehlerhaftes oder fehlendes Token bis grpcNOT_FOUND für einen fehlenden Bucket. Für asynchrone Arbeit liefern OnGRPCResponse, OnGRPCError und OnGRPCException dieselben Informationen über Ereignisse.

Verfügbarkeit

Der typisierte Google-Cloud-Storage-gRPC-Client ist Teil der sgcWebSockets Enterprise Edition. Ein vollständiges, sofort lauffähiges Beispiel befindet sich in Demos\21.GRPC\15.Cloud_Storage und deckt Authentifizierung, Auflisten und Erstellen von Buckets sowie Auflisten von Objekten ab. Die vollständige Referenz finden Sie auf der gRPC-Client-Produktseite.

Fragen oder Feedback? Nehmen Sie Kontakt auf. Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.