# Remodeler une réponse

> Objectif : ne servir que ce que le contrat publie, masquer des données personnelles, traduire les statuts non standard d'un amont - sans toucher à l'amont.

Guide - Depuis la version 1.2.0 - Flexway v1.6.3 - https://flexway.io/docs/operations-response-body/

> 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** : ne servir que ce que le contrat publie, masquer des données personnelles, traduire
les statuts non standard d'un amont - sans toucher à l'amont.

**Commande** - trois politiques dans `flexway.yaml`, attachées à l'opération ou à des routes :

```yaml
policies:
  definitions:
    public-order:
      type: transform-body
      config: { project: [id, status, total, items, customer], on_missing: fail }   # liste fermée ; fail | omit
    no-pii:
      type: redact
      config: { fields: [body.customer.email, body.customer.phone], with: "***" }   # ou remove: true
    legacy-errors:
      type: map-status
      config:
        - { from: 200, when: "has(body.error)", to: 422, code: legacy_rejected }    # condition CEL sur le corps
        - { from: 520, to: 502 }
```

**Vérif** : `GET /orders/7` ne rend que les champs listés, `customer.email` vaut `"***"` ; un `200`
qui porte `error` arrive en `422` `application/problem+json` (`code: legacy_rejected`), sans les mots
de l'amont ; `flexway_policy_executions_total{phase="response"}` compte chaque politique appliquée, par opération, et `flexway_policy_skipped_total` celles que leur condition a ignorées (`1.2.0`).

| Règle | Ce qu'elle veut dire |
| --- | --- |
| Ordre | `map-status` décide du statut, puis `transform-body`, puis `redact` - quel que soit l'ordre de la chaîne |
| Coût | Le corps de ces opérations est **lu en entier** (JSON seulement) ; toutes les autres restent en relais direct |
| Succès projetés | `transform-body` ne touche que les `2xx` ; `redact` masque toute réponse, erreurs comprises |
| Erreur produite | `map-status` vers un `4xx`/`5xx` : problème RFC 9457, corps de l'amont abandonné ; vers un succès : il doit être déclaré par l'opération |
| Jamais brut | Au-delà de `server.body.max_bytes` (1 Mio) : `502` `response_too_large` ; un corps illisible ou non JSON : `502` `upstream_error` - jamais servi tel quel |
| Coupe-circuit | Il compte le code **amont** : un `503` servi en `422` reste une panne |
| Refusé au chargement | Un flux, une réponse non JSON, gRPC, l'inférence ; une projection qui retire un champ **requis** ou garde un champ non déclaré ; un masque du mauvais type ; un exemple du contrat qui, transformé, ne tient plus son schéma - le message nomme l'opération |
| Conformité | `server.body.validate_sample` (`0.01`) des corps servis validés contre le contrat : un écart compte `flexway_policy_nonconformant_total`, jamais un refus ; rechargeable |
| Cache | Le cache garde la réponse de l'amont ; un succès de cache est transformé comme un échec |

Exemple complet : [Corps et statut de réponse](https://flexway.io/docs/operations-examples-gateway/#corps-et-statut-de-r%C3%A9ponse).
