Skip to main content

body-transformer

Rewrites request and response bodies with templates.

Category TransformationAdd it to Route, Service, Consumer, Consumer group, Global rule, Plugin configEngine plugin body-transformerPriority 1080

What it does​

body-transformer writes a new body from a template, for the request the backend receives, for the answer the client gets back, or for both. Under Request or Response, Input format says how the body is decoded, and Template writes the new one from its fields by name.

The template, not the client, decides the shape the other side gets. A value written in double braces is written as text, so a list or an object needs _escape_json to reach the backend as JSON.

When to use it​

  • A new orders service expects customer_id where the mobile app still sends id, and the app cannot be released again this month.
  • A backend answers in xml, and the clients of the route read JSON only.
  • An old partner client posts form fields, read with the encoded format, to a route whose backend takes a JSON body.
  • A backend wraps every answer in an envelope the clients do not need, and the route should hand on only the part inside it.

Not for changing the path, Host or headers the backend receives — see proxy-rewrite (Rewrites the request URI, method, host and headers before proxying), changing the status or headers of the answer, or a fixed body — see response-rewrite (Rewrites the response status, headers and body) or refusing a request whose body does not match a schema — see request-validation (Validates request headers and body against a JSON Schema).

Set it up​

Reshape the request body into the fields the service expects​

_escape_json writes a field back as JSON; a field written in double braces is HTML-escaped text, and a list or an object written that way is not JSON.

Fill Request as in the JSON below.

body-transformer · as the console saves it
{
"request": {
"input_format": "json",
"template": "{\"customer_id\": {*_escape_json(id)*}, \"items\": {*_escape_json(items)*}}"
}
}

Things to know​

  • Template — With _escape_json, a value reaches the backend as JSON: a body with id set to 42/a&b and a list of items arrives with customer_id at 42/a&b and the items list whole, A1 included.
  • Template — Checked only when a request arrives. A template that does not compile is saved anyway, and every request then answers 503.
  • Input format — Six formats are taken, args, encoded, json, multipart, plain and xml; yaml is refused when you save.
  • Input format — On a GET the query string is read whatever this says, and with nothing set the request’s own content type decides.
  • Template is base64 — Unless the format is args or encoded, a template that reads as base64 is decoded anyway, even with this off and when the content type picks the format.
  • Template — Checked only when a response arrives. A template that does not compile is saved anyway, and clients then get 200 with an empty body.
  • A configuration with neither Request nor Response is refused when you save.
  • Request — A side that is set needs its Template: one with only an Input format is refused when you save.
  • Response body limit — A larger answer is not cut cleanly: the template runs twice, on the first bytes and then on nothing, and the client gets both outputs. Where the first bytes do not decode, the upstream's own body comes first.
  • AdviceBefore you save a template on a busy route, send one real request of each shape your clients use through a test route that carries it.

Settings​

The fields as the console shows them, section by section.

RequestrequestobjectRequired unless Response is set
Templaterequest.templatestringRequired

The new request body, where a decoded field is written by name in double braces. _body is the raw body text, not the decoded one. The template language is lua-resty-template; _ctx, _escape_json and _escape_xml are also given to it.

example {"name": "{{name}}"}
Input formatrequest.input_formatstring

The shape the request body is decoded into before the template reads it.

one of args, encoded, json, multipart, plain, xml
Template is base64request.template_is_base64boolean

Decodes the template from base64 before it is compiled.

ResponseresponseobjectRequired unless Request is set
Templateresponse.templatestringRequired

The new response body, where a decoded field of the upstream's answer is written by name in double braces. _body is the raw text. The template language is lua-resty-template; _ctx, _escape_json and _escape_xml are also given to it.

example {"reply": "{{root.reply}}"}
Input formatresponse.input_formatstring

The shape the upstream's body is decoded into before the template reads it. Not set, the answer's content type decides.

one of args, encoded, json, multipart, plain, xml
Template is base64response.template_is_base64boolean

Decodes the template from base64 before it is compiled.

Request body limitmax_req_body_sizeintegerdefault 67108864

The largest request body, in bytes, the plugin reads. A larger one is refused with 413.

at least 1
Response body limitmax_resp_body_sizeintegerdefault 67108864

Bytes of the upstream’s body the template is given.

at least 1

Every plugin also has Enabled, Priority, Filter, Error response and Pre-function: see Plugin execution settings.

G8 dev · Apache APISIX® 3.19.0
Apache, Apache APISIX and APISIX are trademarks of The Apache Software Foundation.
Facts
Category
Transformation
Add it to
Route, Service, Consumer, Consumer group, Global rule, Plugin config
Engine plugin
body-transformer
Priority
1080