Cloud Endpoints est compatible avec le transcodage de protocole, ce qui permet aux clients d'accéder à votre API gRPC en HTTP/JSON. Extensible Service Proxy (ESP) transcode les contenus HTTP/JSON en gRPC.
Ce guide vous explique :
- comment utiliser des annotations dans votre fichier
.proto
pour spécifier la conversion de données HTTP/JSON en gRPC ; - comment déployer votre service dans Endpoints pour utiliser cette fonctionnalité ;
- où trouver plus d'informations de référence sur la conception et la mise en œuvre du transcodage pour les services gRPC.
Nous partons ici du principe que vous avez déjà terminé nos tutoriels gRPC et que vous maîtrisez les concepts de base de Endpoints pour les API gRPC.
Concevoir une API permettant le transcodage
Le transcodage implique de mapper des requêtes HTTP/JSON et leurs paramètres sur les méthodes gRPC et leurs propres paramètres et types de renvois. De ce fait, s'il est possible de mapper une requête HTTP/JSON sur n'importe quelle méthode API arbitraire, cela est facilité si l'API gRPC est elle-même structurée de manière à être orientée ressources, tout comme une API REST HTTP traditionnelle. En d'autres termes, vous devez concevoir le service API de manière à ce qu'il utilise un petit nombre de méthodes standards correspondant à des verbes HTTP tels que GET
et PUT
, qui opèrent sur les ressources du service et sur des collections de ressources, qui constituent elles-mêmes un type de ressource. Ces méthodes standards sont List
, Get
, Create
, Update
et Delete
.
Si nécessaire, l'API peut également comporter des méthodes personnalisées non standards, bien que celles-ci ne soient pas aussi simples à mapper.
Pour plus d'informations sur la conception orientée ressources et les mappages de transcodage standards, consultez notre guide de conception d'API. Il s'agit de la norme suivie par Google lors de la conception d'API publiques telles que les API Cloud. Bien que vous n'ayez pas besoin de suivre ce guide pour utiliser le transcodage gRPC, nous vous le recommandons vivement. En particulier, les pages suivantes vous aideront à comprendre ces principes de conception et à ajouter des mappages de transcodage utiles à vos méthodes :
- Conception orientée ressources
- Méthodes standards
- Méthodes personnalisées
- Verbes HTTP : cette page fournit des consignes supplémentaires pour mettre en œuvre vos méthodes si celles-ci sont accessibles via le protocole HTTP.
La page de référence suivante peut également être utile :
- Informations de référence relatives aux règles HTTP : documentation de référence exhaustive sur les règles de mappage HTTP.
Dans la suite de ce document, vous vous servirez de l'exemple Bookstore que vous avez utilisé dans nos tutoriels, qui repose déjà sur ces principes.
La librairie dispose de collections "shelf" (étagère) de ressources "book" (livre), que les utilisateurs peuvent répertorier (List
), récupérer (Get
), créer (Create
) ou supprimer (Delete
).
Où configurer le transcodage
Le transcodage gRPC est activé par défaut et vous pouvez l'utiliser sans configuration de votre part. Suivez les instructions pour déployer un service utilisant le transcodage.
Ensuite, lorsque vous envoyez une requête HTTP POST
au chemin d'URL GRPC_SERVICE_FULL_NAME/METHOD_NAME>
avec, pour le champ de message de requête correspondant à la méthode, des valeurs (le cas échéant) sous forme de contenus JSON dans le corps de la requête HTTP, ESP envoie le message de requête à la méthode gRPC appropriée. Dans l'exemple précédent, GRPC_SERVICE_FULL_NAME
est le nom complet de votre service tandis que METHOD_NAME
est le nom de la méthode.
Par exemple, si vous envoyez un POST
à l'URL ListShelves
de Bookstore comme suit :
curl -XPOST http://mydomain/endpoints.examples.bookstore.Bookstore/ListShelves
… vous devriez obtenir une liste à jour des étagères au format JSON.
Cependant, en termes de conception d'interface HTTP, il est nettement préférable de configurer explicitement les mappages, comme décrit dans la suite de ce document.
La norme de configuration de l'API gRPC pour la configuration de service vous permet de spécifier exactement comment les données HTTP/JSON doivent être converties en gRPC. Deux mécanismes sont disponibles pour cela : les annotations directes du fichier .proto
et, en YAML, le paramétrage de votre fichier de configuration de l'API gRPC. Nous vous recommandons d'utiliser les annotations du fichier proto
, ce qui facilite la lecture et la maintenance.
Pour plus d'informations sur la configuration YAML et sur les cas où vous devrez peut-être l'utiliser, consultez la section Configurer le transcodage en YAML.
Voici un exemple issu de Bookstore qui est basé sur l'approche que nous recommandons :
// Returns a specific bookstore shelf.
rpc GetShelf(GetShelfRequest) returns (Shelf) {
// Client example - returns the first shelf:
// curl http://DOMAIN_NAME/v1/shelves/1
option (google.api.http) = { get: "/v1/shelves/{shelf}" };
}
...
// Request message for GetShelf method.
message GetShelfRequest {
// The ID of the shelf resource to retrieve.
int64 shelf = 1;
}
L'annotation indique à ESP qu'une requête HTTP GET
avec l'URL http://mydomain/v1/shelves/1
appelle la méthode GetShelf()
du serveur gRPC, avec un GetShelfRequest
contenant l'ID d'étagère demandé shelf
(dans ce cas, 1
).
Ajouter des mappages de transcodage
Cette section décrit quelques annotations de mappage supplémentaires, toujours en se basant sur l'exemple Bookstore. L'exemple Bookstore contient deux exemples de fichiers proto
afin que vous puissiez le déployer avec ou sans les mappages de transcodage et comparer les différences entre les fichiers proto
:
bookstore.proto
: utilisé dans les tutoriels Endpoints, il n'inclut pas les mappages de transcodage.http_bookstore.proto
: inclut les liaisons de transcodage.
Pour des informations plus complètes sur la spécification de mappages de transcodage, consultez les rubriques Méthodes standards et Méthodes personnalisées, ainsi que les informations de référence relatives aux règles HTTP.
Mapper une méthode List
La méthode List
est définie dans le fichier .proto
avec son type de réponse :
// Returns a list of all shelves in the bookstore. rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) { // Define HTTP mapping. // Client example (Assuming your service is hosted at the given 'DOMAIN_NAME'): // curl http://DOMAIN_NAME/v1/shelves option (google.api.http) = { get: "/v1/shelves" }; } ... message ListShelvesResponse { // Shelves in the bookstore. repeated Shelf shelves = 1; }
L'annotation en gras spécifie le mappage HTTP pour cette méthode.
option (google.api.http)
indique qu'il s'agit d'une annotation de mappage HTTP/gRPC.get
indique que cette méthode est mappée sur une requêteGET
HTTP."/v1/shelves"
est le modèle de chemin d'URL (ajouté au domaine de votre service) que la requêteGET
utilise pour appeler cette méthode. Il est également appelé chemin de ressource, car il spécifie généralement l'objet ou la ressource que vous souhaitez utiliser : dans ce cas, toutes les ressources "shelf" de notre Bookstore.
Ainsi, par exemple, si un client appelle cette méthode en envoyant un GET
à l'URL http://mydomain/v1/shelves
, ESP appelle la méthode gRPC ListShelves()
. Le backend gRPC renvoie ensuite les étagères (shelves), qu'ESP convertit au format JSON et renvoie au client.
Mapper une méthode Get
La méthode GetShelf
de Bookstore est définie dans le fichier .proto
avec ses types de requête et de réponse :
// Returns a specific bookstore shelf. rpc GetShelf(GetShelfRequest) returns (Shelf) { // Client example - returns the first shelf: // curl http://DOMAIN_NAME/v1/shelves/1 option (google.api.http) = { get: "/v1/shelves/{shelf}" }; } ... // Request message for GetShelf method. message GetShelfRequest { // The ID of the shelf resource to retrieve. int64 shelf = 1; } ... // A shelf resource. message Shelf { // A unique shelf id. int64 id = 1; // A theme of the shelf (fiction, poetry, etc). string theme = 2; }
L'annotation en gras spécifie le mappage HTTP pour cette méthode.
option (google.api.http)
indique qu'il s'agit d'une annotation de mappage HTTP/gRPC.get
indique que cette méthode est mappée sur une requêteGET
HTTP."/v1/shelves/{shelf}"
est, comme précédemment, le chemin d'URL de la requête, mais le chemin indiqué ici est/v1/shelves/
, puis{shelf}
. Cette notation entre accolades indique à ESP que tout ce qui se trouve dans{shelf}
est la valeur qu'il doit fournir pourshelf
dans le paramètreGetShelfRequest
de la méthode.
Si un client appelle cette méthode en envoyant un GET
à l'URL http://mydomain/v1/shelves/4
, ESP crée un GetShelfRequest
avec une valeur shelf
de 4
, puis l'utilise pour appeler la méthode gRPC GetShelf()
. Le backend gRPC renvoie ensuite le Shelf
demandé ayant l'ID 4
, qu'ESP convertit au format JSON et renvoie au client.
Cette méthode ne nécessite qu'une seule valeur de champ de requête devant être fournie par le client (shelf
). Nous la spécifions dans le modèle de chemin d'URL avec notre notation de capture entre accolades. Si nécessaire, vous pouvez également capturer plusieurs parties de l'URL pour identifier la ressource demandée. Par exemple, la méthode GetBook
nécessite que le client spécifie à la fois l'ID d'étagère (shelf) et l'ID de livre (book) dans l'URL :
// Returns a specific book.
rpc GetBook(GetBookRequest) returns (Book) {
// Client example - get the first book from the second shelf:
// curl http://DOMAIN_NAME/v1/shelves/2/books/1
option (google.api.http) = { get: "/v1/shelves/{shelf}/books/{book}" };
}
...
// Request message for GetBook method.
message GetBookRequest {
// The ID of the shelf from which to retrieve a book.
int64 shelf = 1;
// The ID of the book to retrieve.
int64 book = 2;
}
Outre les littéraux et les accolades de capture de valeurs de champ, les modèles de chemin d'URL peuvent faire appel à des caractères génériques pour indiquer que tout élément figurant dans un segment donné de l'URL doit être capturé. La notation {shelf}
utilisée dans l'exemple précédent est en réalité une version abrégée de {shelf=*}
. Pour en savoir plus sur les règles applicables aux modèles de chemin d'accès, consultez les informations de référence relatives aux règles HTTP.
Dans le cas de ce type de méthode, il n'y a pas de corps de requête HTTP. Vous trouverez davantage de consignes relatives au mappage des méthodes Get
(y compris avec des paramètres de requête) dans la rubrique Méthodes standards.
Mapper une méthode Create
La méthode CreateShelf
de Bookstore est mappée sur la méthode HTTP POST
.
// Creates a new shelf in the bookstore. rpc CreateShelf(CreateShelfRequest) returns (Shelf) { // Client example: // curl -d '{"theme":"Music"}' http://DOMAIN_NAME/v1/shelves option (google.api.http) = { post: "/v1/shelves" body: "shelf" }; } ... // Request message for CreateShelf method. message CreateShelfRequest { // The shelf resource to create. Shelf shelf = 1; } ... // A shelf resource. message Shelf { // A unique shelf id. int64 id = 1; // A theme of the shelf (fiction, poetry, etc). string theme = 2; }
option (google.api.http)
indique qu'il s'agit d'une annotation de mappage HTTP/gRPC.post
indique que cette méthode est mappée sur une requêtePOST
HTTP."/v1/shelves"
est le chemin d'URL de la requête, comme précédemment.body: "shelf"
est utilisé dans le corps de la requête HTTP pour spécifier, au format JSON, la ressource que vous souhaitez insérer.
Ainsi, par exemple, si un client appelle cette méthode comme ceci :
curl -d '{"theme":"Music"}' http://DOMAIN_NAME/v1/shelves
ESP utilise le corps JSON pour créer une valeur Shelf
associée au thème "Music"
pour la requête CreateShelfRequest
, puis appelle la méthode gRPC CreateShelf()
. Le client ne fournit pas la valeur id
pour l'objet Shelf
.
Les ID d'étagère de Bookstore sont fournis par le service lors de la création d'une étagère.
C'est le type d'information que vous devez fournir aux utilisateurs de votre service dans la documentation de l'API.
Utiliser un caractère générique dans le corps
Le nom spécial *
peut être utilisé dans le mappage du corps pour indiquer que tout champ non lié par le modèle de chemin d'accès doit être mappé au corps de la requête.
Ceci active la définition alternative suivante pour la méthode CreateShelf
de mise à jour.
// Creates a new shelf in the bookstore. rpc CreateShelf(CreateShelfRequest) returns (Shelf) { // Client example: // curl -d '{"shelf_theme":"Music", "shelf_size": 20}' http://DOMAIN_NAME/v1/shelves/123 option (google.api.http) = { post: "/v1/shelves/{shelf_id}" body: "*" }; } ... // Request message for CreateShelf method. message CreateShelfRequest { // A unique shelf id. int64 shelf_id = 1; // A theme of the shelf (fiction, poetry, etc). string shelf_theme = 2; // The size of the shelf int64 shelf_size = 3; }
option (google.api.http)
indique qu'il s'agit d'une annotation de mappage HTTP/gRPC.post
indique que cette méthode est mappée sur une requêtePOST
HTTP."/v1/shelves/{shelf_id}"
est le chemin d'URL de la requête. La valeur présente dans{shelf_id}
correspond à la valeur du champshelf_id
dansCreateShelfRequest
.body: "*"
est utilisé dans le corps de la requête HTTP pour spécifier tous les champs de requête restants, à l'exception deshelf_id
dans cet exemple, qui sontshelf_theme
etshelf_size
. Les valeurs de tous les champs du corps JSON contenant ces deux noms seront utilisés dans les champs correspondants deCreateShelfRequest
.
Par exemple, si un client appelle cette méthode de la façon suivante :
curl -d '{"shelf_theme":"Music", "shelf_size": 20}' http://DOMAIN_NAME/v1/shelves/123
ESP utilise le corps JSON et le modèle de chemin pour créer un CreateShelfRequest{shelf_id: 123 shelf_theme: "Music" shelf_size: 20}
, puis l'utilise pour appeler la méthode gRPC CreateShelf()
. Pour plus de détails, consultez la HttpRule.
Configurer le transcodage en YAML
Une approche alternative consiste à spécifier vos mappages HTTP vers gRPC dans le fichier YAML de configuration de l'API gRPC plutôt que dans le fichier .proto
. Configurer le transcodage dans un fichier YAML peut être nécessaire si vous avez une seule définition d'API proto
utilisée au sein de plusieurs services, des mappages différents étant spécifiés pour chaque service.
Les règles (rules
) de la section http
de votre fichier YAML indiquent comment mapper des requêtes HTTP/JSON avec des méthodes gRPC :
http:
rules:
...
#
# 'GetShelf' is available via the GET HTTP verb and '/shelves/{shelf}' URL
# path, where {shelf} is the value of the 'shelf' field of 'GetShelfRequest'
# protobuf message.
#
# Client example - returns the first shelf:
# curl http://DOMAIN_NAME/v1/shelves/1
#
- selector: endpoints.examples.bookstore.Bookstore.GetShelf
get: /v1/shelves/{shelf}
...
Un exemple plus complet basé sur cette approche pour notre exemple de service Bookstore est disponible dans api_config_http.yaml
.
Déployer un service utilisant le transcodage
Le déploiement d'un service gRPC utilisant le transcodage est sensiblement identique à celui de tout autre service gRPC, avec une différence majeure. Dans les tutoriels, l'exemple devait uniquement accepter les requêtes gRPC en provenance du client d'exemple. Toutefois, si l'application Bookstore doit également accepter les requêtes HTTP, vous devez compléter la configuration pour ESP. Les clients utilisent le protocole HTTP1.1
pour envoyer des requêtes JSON/HTTP à ESP. Par conséquent, ESP doit être configuré pour utiliser SSL (le port SSL est compatible avec les deux types de requêtes) ou un port spécial doit avoir été activé pour accepter ces requêtes. Le déploiement est par ailleurs sensiblement identique à celui décrit dans le tutoriel de l'environnement choisi.
Vérifier que les règles HTTP sont déployées
Si vous avez déjà téléchargé notre exemple Bookstore pour nos tutoriels, vous devez télécharger une version légèrement différente du fichier .proto
comportant des annotations, http_bookstore.proto
.
Vous devrez également cloner le dépôt googleapis
à partir de GitHub avant d’exécuter protoc
, car vous aurez besoin d'annotations.proto
dans votre chemin d’inclusion.
git clone https://github.com/googleapis/googleapis
GOOGLEAPIS_DIR=<your-local-googleapis-folder>
Créez ensuite un descripteur .pb
à partir de http_bookstore.proto
lors du déploiement de votre configuration sur Endpoints :
protoc \
--include_imports \
--include_source_info \
--proto_path=${GOOGLEAPIS_DIR} \
--proto_path=. \
--descriptor_set_out=api_descriptor.pb \
http_bookstore.proto
Si vous utilisez la méthode alternative de configuration des mappages HTTP dans votre fichier YAML de configuration de l'API gRPC, vous devez également vous assurer que les règles pertinentes sont mises en place lors du déploiement de votre configuration sur Endpoints. Pour essayer cela avec le service Bookstore, ses règles de base sont dans le fichier api_config.yaml
et ses règles HTTP dans le fichier api_config_http.yaml
:
gcloud endpoints services deploy api_descriptor.pb api_config.yaml api_config_http.yaml
Utiliser SSL
Si SSL est activé pour la communication entre vos clients et ESP, les clients peuvent alors effectuer des appels gRPC ou HTTP1.1
sur le même port. Pour savoir comment configurer SSL pour un service Endpoints, consultez la rubrique concernant l'activation de SSL.
Spécifiez un port permettant à ESP d'accepter les appels SSL à l'aide de l'indicateur --ssl_port
dans le fichier de configuration de Google Kubernetes Engine (GKE) ou de la commande docker run
(Compute Engine/Docker).
args: [
"--http_port", "8080",
"--ssl_port", "443", # enable SSL port at 443 to serve https requests
"--backend", "grpc://127.0.0.1:8081", # gRPC backend.
"--service", "SERVICE_NAME",
"--rollout_strategy", "managed",
]
Configurer un port HTTP1.1
Si vous n'utilisez pas SSL, vous devez configurer un port distinct pour les requêtes HTTP1.1
car, sans SSL, gRPC et HTTP1.1
ne peuvent pas partager le même port. Utilisez l'indicateur --http_port
dans le fichier de configuration GKE ou la commande docker run
pour spécifier un port destiné à recevoir les appels HTTP1.1
. Si vous souhaitez également que ESP accepte les appels gRPC, vous devez aussi utiliser l'indicateur --http2_port
pour spécifier un port gRPC.
args: [
"--http_port", "8080", # for HTTP 1.1
"--http2_port", "8090", # for gRPC
"--backend", "grpc://127.0.0.1:8081", # gRPC backend.
"--service", "SERVICE_NAME",
"--rollout_strategy", "managed",
]
Appeler un service utilisant le transcodage
Cette section décrit la configuration du service et explique comment passer des appels HTTP au service.
Configurer le service
Cette section part du principe que vous avez déjà suivi les tutoriels élémentaires relatifs au service gRPC dans l'environnement de votre choix, et que vous disposez d'un cluster GKE ou d'une instance Compute Engine pour exécuter l'exemple.
- Commencez par vérifier que vous avez déployé la configuration du service Bookstore compatible avec HTTP sur Endpoints, comme décrit dans la section Vérifier que les règles HTTP sont déployées.
Déployez le backend et ESP comme décrit dans le tutoriel correspondant à la plate-forme de votre choix en vous servant de l'indicateur
--http_port
pour activer un port pour les requêtesHTTP1.1
:- Déploiement sur GKE : suivez les instructions de la section Déployer l'exemple d'API et ESP sur le cluster en veillant à ce que l'indicateur
"--http_port"
soit spécifié dans le fichier de configuration GKE. - Déploiement sur Compute Engine : suivez les instructions de la section Exécuter l'exemple d’API et ESP dans un conteneur Docker.
Veillez à ce que l'indicateur
--http_port
soit spécifié dans la commandedocker run
lors de l'exécution du conteneur Docker prêt à l'emploi d'ESP.
- Déploiement sur GKE : suivez les instructions de la section Déployer l'exemple d'API et ESP sur le cluster en veillant à ce que l'indicateur
Envoyer des appels HTTP au service
- Obtenez l'adresse IP externe d'ESP et définissez-la en tant que
$ESP_IP
. Envoyez la requête HTTP suivante avec
curl
curl http://$ESP_IP/v1/shelves
(ou utilisez la même URL avec
https://
si vous vous servez de SSL). Le serveur doit envoyer la réponse suivante :{"shelves":[{"id":"1","theme":"Fiction"},{"id":"2","theme":"Fantasy"}]}
Si la sortie affiche une réponse binaire, vérifiez la configuration du port. Vous accédez peut-être au port HTTP2 au lieu du port HTTP.
Essayez une méthode
Create
.CreateShelf
nécessite une clé API. Vous devez donc créer une clé pour votre projet et la définir en tant que$KEY
. Effectuez maintenant l'appel suivant :curl -d '{"theme":"Music"}' http://$ESP_IP/v1/shelves?key=$KEY
Si vous appelez à nouveau
GetShelves
, vous devriez voir votre nouvelle étagère.