diff --git a/docs/en/latest/plugins/body-transformer.md b/docs/en/latest/plugins/body-transformer.md
index dc1b78632746..fb1b7f0bcdbd 100644
--- a/docs/en/latest/plugins/body-transformer.md
+++ b/docs/en/latest/plugins/body-transformer.md
@@ -6,7 +6,7 @@ keywords:
- Plugin
- BODY TRANSFORMER
- body-transformer
-description: This document contains information about the Apache APISIX body-transformer Plugin.
+description: The body-transformer plugin performs template-based transformations to transform the request and/or response bodies from one format to another, for example, from JSON to JSON, JSON to HTML, or XML to YAML.
---
-## Description
-
-This plugin is used to transform the request and/or response body from one
-format to another format, e.g. JSON to XML.
+
+
+
-Use cases:
+## Description
-- simple SOAP proxy
-- generic template-based transform, e.g. JSON to JSON, JSON to HTML, XML to YAML
+The `body-transformer` plugin performs template-based transformations to transform the request and/or response bodies from one format to another, for example, from JSON to JSON, JSON to HTML, or XML to YAML.
## Attributes
-| Name | Type | Required | Description |
-| ----------- | ----------- | ----------- | ----------- |
-| `request` | object | False | request body transformation configuration |
-| `request.input_format` | string | False | request body original format, if not specified, it would be determined from `Content-Type` header. |
-| `request.template` | string | True | request body transformation template |
-| `request.template_is_base64` | boolean | False | Set to true if the template is base64 encoded |
-| `response` | object | False | response body transformation configuration |
-| `response.input_format` | string | False | response body original format, if not specified, it would be determined from `Content-Type` header. |
-| `response.template` | string | True | response body transformation template |
-| `response.template_is_base64` | boolean | False | Set to true if the template is base64 encoded |
+| Name | Type | Required | Default | Valid values | Description |
+| ------------- | ------- | -------- | ------- | ------------ | ------------------------------------------ |
+| `request` | object | False | | | Request body transformation configuration. |
+| `request.input_format` | string | False | | [`xml`,`json`,`encoded`,`args`,`plain`,`multipart`] | Request body original media type. If unspecified, the value would be determined by the `Content-Type` header to apply the corresponding decoder. The `xml` option corresponds to `text/xml` media type. The `json` option corresponds to `application/json` media type. The `encoded` option corresponds to `application/x-www-form-urlencoded` media type. The `args` option corresponds to GET requests. The `plain` option corresponds to `text/plain` media type. The `multipart` option corresponds to `multipart/related` media type. If the media type is neither type, the value would be left unset and the transformation template will be directly applied. |
+| `request.template` | string | True | | | Request body transformation template. The template uses [lua-resty-template](https://github.com/bungle/lua-resty-template) syntax. See the [template syntax](https://github.com/bungle/lua-resty-template#template-syntax) for more details. You can also use auxiliary functions `_escape_json()` and `_escape_xml()` to escape special characters such as double quotes, `_body` to access request body, and `_ctx` to access context variables. |
+| `request.template_is_base64` | boolean | False | false | | Set to true if the template is base64 encoded. |
+| `response` | object | False | | | Response body transformation configuration. |
+| `response.input_format` | string | False | | [`xml`,`json`] | Response body original media type. If unspecified, the value would be determined by the `Content-Type` header to apply the corresponding decoder. If the media type is neither `xml` nor `json`, the value would be left unset and the transformation template will be directly applied. |
+| `response.template` | string | True | | | Response body transformation template. |
+| `response.template_is_base64` | boolean | False | false | | Set to true if the template is base64 encoded. |
-## Enable Plugin
+## Examples
-You can enable the Plugin on a specific Route as shown below:
+The examples below demonstrate how you can configure `body-transformer` for different scenarios.
:::note
+
You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command:
```bash
@@ -64,227 +63,547 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"/
:::
+The transformation template uses [lua-resty-template](https://github.com/bungle/lua-resty-template) syntax. See the [template syntax](https://github.com/bungle/lua-resty-template#template-syntax) to learn more.
+
+You can also use auxiliary functions `_escape_json()` and `_escape_xml()` to escape special characters such as double quotes, `_body` to access request body, and `_ctx` to access context variables.
+
+In all cases, you should ensure that the transformation template is a valid JSON string.
+
+### Transform between JSON and XML SOAP
+
+The following example demonstrates how to transform the request body from JSON to XML and the response body from XML to JSON when working with a SOAP upstream service.
+
+Start the sample SOAP service:
+
```shell
-curl http://127.0.0.1:9180/apisix/admin/routes/test_ws \
- -H "X-API-KEY: $admin_key" -X PUT -d '
+cd /tmp
+git clone https://github.com/spring-guides/gs-soap-service.git
+cd gs-soap-service/complete
+./mvnw spring-boot:run
+```
+
+Create the request and response transformation templates:
+
+```shell
+req_template=$(cat <
+
+
+
+ {{_escape_xml(name)}}
+
+
+
+EOF
+)
+
+rsp_template=$(cat <
-
-
-
- {{_escape_xml(name)}}
-
-
-
-EOF
-)
+```shell
+body='
+foobar:
+ foo: hello
+ bar: world'
+
+curl "http://127.0.0.1:9080/anything" -X POST \
+ -d "$body" \
+ -H "Content-Type: text/yaml" \
+ -i
+```
-rsp_template=$(cat < 18 then
+ context._multipart:set_simple("status", "adult")
+ else
+ context._multipart:set_simple("status", "minor")
+ end
+
+ local body = context._multipart:tostring()
+%}{* body *}
+EOF
+)
+```
+
+Create a route with `body-transformer`, which sets the `input_format` to `multipart` and uses the previously created request template for transformation:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${ADMIN_API_KEY}" \
+ -d '{
+ "id": "body-transformer-route",
+ "uri": "/anything",
+ "plugins": {
+ "body-transformer": {
+ "request": {
+ "input_format": "multipart",
+ "template": "'"$req_template"'"
}
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
}
-}'
+ }'
+```
+
+Send a multipart POST request to the route:
+
+```shell
+curl -X POST \
+ -F "name=john" \
+ -F "age=10" \
+ "http://127.0.0.1:9080/anything"
+```
+
+You should see a response similar to the following:
+
+```json
+{
+ "args": {},
+ "data": "",
+ "files": {},
+ "form": {
+ "age": "10",
+ "name": "john",
+ "status": "minor"
+ },
+ "headers": {
+ "Accept": "*/*",
+ "Content-Length": "361",
+ "Content-Type": "multipart/form-data; boundary=------------------------qtPjk4c8ZjmGOXNKzhqnOP",
+ ...
+ },
+ ...
+}
```
diff --git a/docs/zh/latest/config.json b/docs/zh/latest/config.json
index d3a8c71232ce..00d89703babb 100644
--- a/docs/zh/latest/config.json
+++ b/docs/zh/latest/config.json
@@ -82,6 +82,7 @@
"plugins/grpc-web",
"plugins/fault-injection",
"plugins/mocking",
+ "plugins/body-transformer",
"plugins/attach-consumer-label"
]
},
diff --git a/docs/zh/latest/plugins/body-transformer.md b/docs/zh/latest/plugins/body-transformer.md
new file mode 100644
index 000000000000..6717dfcf0b13
--- /dev/null
+++ b/docs/zh/latest/plugins/body-transformer.md
@@ -0,0 +1,609 @@
+---
+title: body-transformer
+keywords:
+ - Apache APISIX
+ - API 网关
+ - Plugin
+ - BODY TRANSFORMER
+ - body-transformer
+description: body-transformer 插件执行基于模板的转换,将请求和/或响应主体从一种格式转换为另一种格式,例如从 JSON 到 JSON、从 JSON 到 HTML 或从 XML 到 YAML。
+---
+
+
+
+
+
+
+
+## 描述
+
+`body-transformer` 插件执行基于模板的转换,将请求和/或响应主体从一种格式转换为另一种格式,例如从 JSON 到 JSON、从 JSON 到 HTML 或从 XML 到 YAML。
+
+## 属性
+
+| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
+|--------------|----------------------|-------|---------------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------|
+| `request` | object | 否 | | | 请求体转换配置。 |
+| `request.input_format` | string | 否 | | [`xml`,`json`,`encoded`,`args`,`plain`,`multipart`] | 请求体原始媒体类型。若未指定,则该值将由 `Content-Type` 标头确定以应用相应的解码器。`xml` 选项对应于 `text/xml` 媒体类型。`json` 选项对应于 `application/json` 媒体类型。`encoded` 选项对应于 `application/x-www-form-urlencoded` 媒体类型。`args` 选项对应于 GET 请求。`plain` 选项对应于 `text/plain` 媒体类型。`multipart` 选项对应于 `multipart/related` 媒体类型。如果媒体类型不是这两种类型,则该值将保留未设置状态并直接应用转换模板。 |
+| `request.template` | string | True | | | 请求体转换模板。模板使用 [lua-resty-template](https://github.com/bungle/lua-resty-template) 语法。有关更多详细信息,请参阅 [模板语法](https://github.com/bungle/lua-resty-template#template-syntax)。您还可以使用辅助函数 `_escape_json()` 和 `_escape_xml()` 转义双引号等特殊字符,使用 `_body` 访问请求正文,使用 `_ctx` 访问上下文变量。|
+| `request.template_is_base64` | boolean | 否 | false | | 如果模板是 base64 编码的,则设置为 true。|
+| `response` | object | 否 | | | 响应体转换配置。|
+| `response.input_format` | string | 否 | | [`xml`,`json`] | 响应体原始媒体类型。如果未指定,则该值将由 `Content-Type` 标头确定以应用相应的解码器。如果媒体类型既不是 `xml` 也不是 `json`,则该值将保留未设置状态,并直接应用转换模板。|
+| `response.template` | string | True | | | 响应主体转换模板。|
+| `response.template_is_base64` | boolean | 否 | false | | 如果模板是 base64 编码的,则设置为 true。|
+
+## 示例
+
+以下示例演示了如何针对不同场景配置 `body-transformer`。
+
+:::note
+
+您可以这样从 `config.yaml` 中获取 `admin_key` 并存入环境变量:
+
+```bash
+admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
+```
+
+:::
+
+转换模板使用 [lua-resty-template](https://github.com/bungle/lua-resty-template) 语法。请参阅 [模板语法](https://github.com/bungle/lua-resty-template#template-syntax) 了解更多信息。
+
+您还可以使用辅助函数 `_escape_json()` 和 `_escape_xml()` 转义特殊字符(例如双引号)、`_body` 访问请求正文以及 `_ctx` 访问上下文变量。
+
+在所有情况下,您都应确保转换模板是有效的 JSON 字符串。
+
+### JSON 和 XML SOAP 之间的转换
+
+以下示例演示了在使用 SOAP 上游服务时如何将请求主体从 JSON 转换为 XML,将响应主体从 XML 转换为 JSON。
+
+启动示例 SOAP 服务:
+
+```shell
+cd /tmp
+git clone https://github.com/spring-guides/gs-soap-service.git
+cd gs-soap-service/complete
+./mvnw spring-boot:run
+```
+
+创建请求和响应转换模板:
+
+```shell
+req_template=$(cat <
+
+
+
+ {{_escape_xml(name)}}
+
+
+
+EOF
+)
+
+rsp_template=$(cat < 18 then
+ context._multipart:set_simple("status", "adult")
+ else
+ context._multipart:set_simple("status", "minor")
+ end
+
+ local body = context._multipart:tostring()
+%}{* body *}
+EOF
+)
+```
+
+创建一个带有 `body-transformer` 的路由,将 `input_format` 设置为 `multipart`,并使用之前创建的请求模板进行转换:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${ADMIN_API_KEY}" \
+ -d '{
+ "id": "body-transformer-route",
+ "uri": "/anything",
+ "plugins": {
+ "body-transformer": {
+ "request": {
+ "input_format": "multipart",
+ "template": "'"$req_template"'"
+ }
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+向路由发送多部分 POST 请求:
+
+```shell
+curl -X POST \
+ -F "name=john" \
+ -F "age=10" \
+ "http://127.0.0.1:9080/anything"
+```
+
+您应该会看到类似以下内容的响应:
+
+```json
+{
+ "args": {},
+ "data": "",
+ "files": {},
+ "form": {
+ "age": "10",
+ "name": "john",
+ "status": "minor"
+ },
+ "headers": {
+ "Accept": "*/*",
+ "Content-Length": "361",
+ "Content-Type": "multipart/form-data; boundary=------------------------qtPjk4c8ZjmGOXNKzhqnOP",
+ ...
+ },
+ ...
+}
+```