# Un amont gRPC

> Objectif : servir un service gRPC à des clients gRPC, à un navigateur (gRPC-Web) et en REST/JSON, depuis son seul .proto.

Guide - Depuis la version 1.1.0 - Flexway v1.6.3 - https://flexway.io/docs/operations-grpc/

> Guide d'exploitation : configurer, déployer et observer la passerelle. Ce que fait la capacité côté produit : [guide produit](https://flexway.io/docs/product-overview/) ; l'appeler : [guide développeur](https://flexway.io/docs/developer-overview/).

**Objectif** : servir un service gRPC à des clients gRPC, à un navigateur (gRPC-Web) et en
REST/JSON, depuis son seul `.proto`.

**Commande** - l'équipe de l'amont annote son `.proto` : la correspondance REST standard
(`google.api.http`) et ce dont Flexway a besoin en plus (`flexway.v1.operation`, le pendant des
`x-flexway-*`). Puis elle construit le jeu de descripteurs :

```proto
syntax = "proto3";
package shop.v1;                          // le nom gRPC est shop.v1.Orders/GetOrder

import "flexway/v1/options.proto";       // à copier depuis le tag que vous exécutez : services/gateway/api/flexway/v1/options.proto
import "google/api/annotations.proto";   // depuis buf.build/googleapis/googleapis, ci-dessous

service Orders {
  rpc GetOrder(GetOrderRequest) returns (Order) {
    option (google.api.http) = { get: "/v1/shop/orders/{id}" };
    option (flexway.v1.operation) = { upstream: "orders" security: [ { scopes: ["orders:read"] } ] };
  }
}
```

```bash
v=<version>   # le Flexway que vous exécutez
mkdir -p flexway/v1 && curl -fsSLo flexway/v1/options.proto \
  "https://raw.githubusercontent.com/flexwiz/flexway/v$v/services/gateway/api/flexway/v1/options.proto"
cat > buf.yaml <<'YAML'
version: v2
deps: [buf.build/googleapis/googleapis]
YAML
buf dep update
buf build -o orders.binpb       # ou : protoc --include_imports --descriptor_set_out=orders.binpb ...
```

```yaml
contracts:
  protobuf: [./orders.binpb]
upstreams:
  orders: { url: http://orders.internal:9000, protocol: grpc }   # h2c dans un maillage
```

**Vérif** :

```bash
grpcurl -plaintext -protoset orders.binpb -H "authorization: Bearer $TOKEN" \
  -d '{"id":"42"}' localhost:8080 shop.v1.Orders/GetOrder               # gRPC, sur le port de trafic
curl -H "authorization: Bearer $TOKEN" localhost:8080/v1/shop/orders/42  # la même opération en REST
```

Les deux appels sont **une seule opération**, `shop.v1.Orders/GetOrder` : même identité, même
débit, même quota, même ligne d'audit. Un refus arrive en `google.rpc.Status` au client gRPC (le
code du problème dans `ErrorInfo.reason`), en RFC 9457 au client REST. Une erreur de l'amont arrive
au client REST en problème `upstream_status`, son statut gRPC dans l'extension `grpc`. Un flux
serveur est un `text/event-stream` en REST.

> Pour un **navigateur** (gRPC-Web), la politique `cors` expose `grpc-status`, `grpc-message` et
> `grpc-status-details-bin` (`expose_headers`) et accepte `x-grpc-web`, `x-user-agent` et
> `grpc-timeout` (`allow_headers`) : sans eux, le navigateur ne lit pas un refus. Refusés au
> chargement à cette version : variable sur plusieurs segments (`{name=shelves/*}`), joker, verbe
> (`:cancel`), `google.api.http` sur un flux client ou bidirectionnel - ceux-là restent servis en
> gRPC seulement.
