Google Cloud Storage via gRPC dans Delphi

· Composants

Google Cloud Storage est le service de stockage d'objets de Google. Les données résident dans des buckets, et chaque bucket contient des objets (fichiers) que vous téléversez, listez, lisez et supprimez. La plupart du code Delphi l'atteint via l'API REST JSON, mais le service de stockage expose aussi une API gRPC qui parle Protocol Buffers sur HTTP/2. sgcWebSockets Enterprise fournit un client gRPC Cloud Storage typé bâti sur TsgcGRPCClient, ce qui vous permet de piloter les buckets et les objets depuis Delphi et C++Builder sans aucun runtime externe ni stubs générés.

Comment ça fonctionne

L'API Storage gRPC réside à storage.googleapis.com:443 et parle le service google.storage.v2.Storage. sgcWebSockets fournit déjà une pile HTTP/2 complète, donc le client typé repose sur un transport TsgcHTTP2Client avec TLS activé. TsgcGRPCClient effectue l'encadrement gRPC, les en-têtes et la gestion des délais d'attente, ouvre le flux HTTP/2, et analyse la réponse et les trailers en un TsgcGRPCResponse.

La couche typée se trouve dans l'unité sgcGRPC_Google_Storage. Elle vous fournit des classes de requête et de réponse telles que TsgcGRPCStorageListBucketsRequest, TsgcGRPCStorageListObjectsResponse et TsgcGRPCStorageBucket qui se sérialisent vers et depuis Protocol Buffers. Vous définissez des propriétés typées, appelez ToBytes pour obtenir la charge utile de la requête, l'envoyez avec Call, et chargez la réponse avec LoadFromBytes. Pas de compilateur protobuf, pas de balises de champ écrites à la main.

L'authentification utilise un compte de service Google. Le client signe un JSON Web Token à partir de la clé du compte de service et le présente sous la forme d'un jeton Bearer dans les métadonnées authorization gRPC, ce qui est la façon standard dont Google Cloud autorise les appels de serveur à serveur.

Configurer le transport

Un canal gRPC n'est qu'une connexion HTTP/2. Pointez un TsgcHTTP2Client vers l'endpoint de stockage avec TLS activé, puis attachez-le à TsgcGRPCClient et sélectionnez le type de contenu Protocol Buffers binaire.

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;

S'authentifier avec un compte de service

Chargez la clé JSON du compte de service, configurez un JWT signé pour l'endpoint de stockage, et placez le jeton obtenu dans DefaultMetadata afin qu'il voyage sur chaque appel. Le JWT auto-signé de compte de service est lié à une audience, donc le API_Endpoint doit pointer vers storage.googleapis.com pour que le jeton soit accepté.

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;

Lister les buckets

Pour énumérer les buckets d'un projet, renseignez un TsgcGRPCStorageListBucketsRequest avec le projet comme Parent, sérialisez-le, et effectuez un Call unaire vers la méthode ListBuckets. Les octets de réponse se chargent directement dans un TsgcGRPCStorageListBucketsResponse, qui expose chaque bucket avec son nom et son emplacement.

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;

Créer un bucket

La création d'un bucket suit le même schéma avec TsgcGRPCStorageCreateBucketRequest. Définissez le projet parent, l'identifiant du nouveau bucket, et le projet qui possède la ressource bucket, puis appelez CreateBucket. La réponse porte le TsgcGRPCStorageBucket créé.

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;

Lister les objets d'un bucket

Lister les objets d'un bucket utilise TsgcGRPCStorageListObjectsRequest. Le parent est le nom de ressource du bucket, sous la forme projects/_/buckets/<bucket>. La réponse vous donne le nom, la taille et le type de contenu de chaque objet, et vous pouvez éventuellement définir Prefix et Delimiter pour parcourir une hiérarchie de type dossier.

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;

Lire et écrire les données d'objet

Au-delà des métadonnées de bucket et d'objet, l'unité couvre aussi les charges utiles des objets. TsgcGRPCStorageReadObjectRequest relit les octets d'un objet, avec ReadOffset et ReadLimit optionnels pour les téléchargements par plage, et la réponse correspondante expose les octets Data bruts. TsgcGRPCStorageWriteObjectRequest téléverse le contenu d'un objet par morceaux : définissez la ressource WriteObjectSpec pour le premier morceau, poussez les Data à des valeurs WriteOffset croissantes, et marquez FinishWrite sur le dernier morceau. Comme chaque message se sérialise via ToBytes et LoadFromBytes, les mêmes classes typées fonctionnent que vous téléversiez un petit fichier en un seul appel ou que vous diffusiez un gros objet en plusieurs morceaux.

Pagination et gestion des erreurs

Les réponses de liste renvoient un NextPageToken lorsque davantage de résultats sont disponibles. Copiez-le dans le PageToken de la requête suivante et rappelez pour paginer à travers de grands buckets ou de longues listes d'objets. Côté erreur, chaque TsgcGRPCResponse porte un StatusCode typé, donc un résultat non-grpcOK vous indique exactement ce qui n'a pas fonctionné, de grpcUNAUTHENTICATED pour un jeton invalide ou manquant à grpcNOT_FOUND pour un bucket manquant. Pour le travail asynchrone, OnGRPCResponse, OnGRPCError et OnGRPCException délivrent les mêmes informations via des événements.

Disponibilité

Le client gRPC Google Cloud Storage typé fait partie de l'édition Enterprise de sgcWebSockets. Un exemple complet et prêt à l'emploi se trouve dans Demos\21.GRPC\15.Cloud_Storage, couvrant l'authentification, la liste et la création de buckets, et la liste des objets. La référence complète est sur la page produit du client gRPC.

Des questions ou des commentaires ? Contactez-nous. Vous recevrez une réponse des personnes qui ont écrit le code.