proxy-rewrite 插件提供了重写 APISIX 转发到上游服务请求的选项。使用该插件,你可以修改 HTTP 方法、请求目标上游地址、请求头等。
示例
以下示例展示了如何在不同场景下的路由上配置 proxy-rewrite。
重写 Host 请求头
以下示例演示了如何修改请求中的 Host 头。请注意,你不应使用 headers.set 来设置 Host 头。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"methods": ["GET"],
"uri": "/headers",
"plugins": {
"proxy-rewrite": {
"host": "myapisix.demo"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
向 /headers 发送请求以检查发送到上游的所有请求头:
curl "http://127.0.0.1:9080/headers"
你应该看到类似于以下的响应:
{
"headers": {
"Accept": "*/*",
"Host": "myapisix.demo",
"User-Agent": "curl/8.2.1",
"X-Amzn-Trace-Id": "Root=1-64fef198-29da0970383150175bd2d76d",
"X-Forwarded-Host": "127.0.0.1"
}
}
重写 URI 并设置请求头
以下示例演示了如何重写请求上游 URI 并设置其他请求头值。如果客户端请求中存在相同的请求头,则插件中设置的相应请求头值将覆盖客户端请求中的值。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"methods": ["GET"],
"uri": "/",
"plugins": {
"proxy-rewrite": {
"uri": "/anything",
"headers": {
"set": {
"X-Api-Version": "v1",
"X-Api-Engine": "apisix"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
发送请求以进行验证:
curl "http://127.0.0.1:9080/" -H '"X-Api-Version": "v2"'
你应该看到类似于以下的响应:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/8.2.1",
"X-Amzn-Trace-Id": "Root=1-64fed73a-59cd3bd640d76ab16c97f1f1",
"X-Api-Engine": "apisix",
"X-Api-Version": "v1",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"method": "GET",
"origin": "::1, 103.248.35.179",
"url": "http://localhost/anything"
}
请注意,现有的请求头和请求中传递的 X-Api-Version 请求头值都被插件中配置的值覆盖。
重写 URI 并追加请求头
以下示例演示了如何重写请求上游 URI 并追加其他请求头值。如果客户端请求中存在相同的请求头,它们的值将追加到插件中配置的请求头值之后。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"methods": ["GET"],
"uri": "/",
"plugins": {
"proxy-rewrite": {
"uri": "/headers",
"headers": {
"add": {
"X-Api-Version": "v1",
"X-Api-Engine": "apisix"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
发送请求以进行验证:
curl "http://127.0.0.1:9080/" -H '"X-Api-Version": "v2"'
你应该看到类似于以下的响应:
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/8.2.1",
"X-Amzn-Trace-Id": "Root=1-64fed73a-59cd3bd640d76ab16c97f1f1",
"X-Api-Engine": "apisix",
"X-Api-Version": "v1,v2",
"X-Forwarded-Host": "127.0.0.1"
}
}
请注意,现有的请求头和请求中传递的 X-Api-Version 请求头值都追加在插件中配置的值之后。
删除现有请求头
以下示例演示了如何删除现有的请求头 User-Agent。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"methods": ["GET"],
"uri": "/headers",
"plugins": {
"proxy-rewrite": {
"headers": {
"remove":[
"User-Agent"
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
发送请求以验证指定的请求头是否已被删除:
curl "http://127.0.0.1:9080/headers"
你应该看到类似于以下的响应,其中 User-Agent 请求头不存在:
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-64fef302-07f2b13e0eb006ba776ad91d",
"X-Forwarded-Host": "127.0.0.1"
}
}
使用正则表达式重写 URI
以下示例演示了如何从原始上游 URI 路径中解析文本,并使用它们来组成新的上游 URI 路径。在此示例中,APISIX 配置为将所有请求从 /test/user/agent 转发到 /user-agent。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"uri": "/test/*",
"plugins": {
"proxy-rewrite": {
"regex_uri": ["^/test/(.*)/(.*)", "/$1-$2"]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
向 /test/user/agent 发送请求以检查是否被重定向到 /user-agent:
curl "http://127.0.0.1:9080/test/user/agent"
你应该看到类似于以下的响应:
{
"user-agent": "curl/8.2.1"
}
添加 URL 参数
以下示例演示了如何向请求添加 URL 参数。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"methods": ["GET"],
"uri": "/get",
"plugins": {
"proxy-rewrite": {
"uri": "/get?arg1=apisix&arg2=plugin"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
发送请求以验证 URL 参数是否也转发到了上游:
curl "http://127.0.0.1:9080/get"
你应该看到类似于以下的响应:
{
"args": {
"arg1": "apisix",
"arg2": "plugin"
},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.2.1",
"X-Amzn-Trace-Id": "Root=1-64fef6dc-2b0e09591db7353a275cdae4",
"X-Forwarded-Host": "127.0.0.1"
},
"origin": "127.0.0.1, 103.248.35.148",
"url": "http://127.0.0.1/get?arg1=apisix&arg2=plugin"
}
重写 HTTP 方法
以下示例演示了如何将 GET 请求重写为 POST 请求。
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-rewrite-route",
"methods": ["GET"],
"uri": "/get",
"plugins": {
"proxy-rewrite": {
"uri": "/anything",
"method":"POST"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
向 /get 发送 GET 请求,以验证它是否被转换为对 /anything 的 POST 请求:
curl "http://127.0.0.1:9080/get"
你应该看到类似于以下的响应:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.2.1",
"X-Amzn-Trace-Id": "Root=1-64fef7de-0c63387645353998196317f2",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"method": "POST",
"origin": "::1, 103.248.35.179",
"url": "http://localhost/anything"
}
将消费者名称转发到上游
以下示例演示了如何将成功通过身份验证的消费者名称转发到上游服务。作为示例,你将使用 key-auth 作为身份验证方法。
创建一个消费者 JohnDoe:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JohnDoe"
}'
为消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/JohnDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
接下来,创建一个启用了密钥身份验证的路由,并配置 proxy-rewrite 以将消费者名称添加到请求头:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "consumer-restricted-route",
"uri": "/get",
"plugins": {
"key-auth": {},
"proxy-rewrite": {
"headers": {
"set": {
"X-Apisix-Consumer": "$consumer_name"
},
"remove": [ "Apikey" ]
}
}
},
"upstream" : {
"nodes": {
"httpbin.org":1
}
}
}'
❶ 使用内置变量将消费者名称添加到请求头 X-Apisix-Consumer。
❷ 删除身份验证密钥,使其对上游服务不可见。
作为消费者 JohnDoe 向路由发送请求:
curl -i "http://127.0.0.1:9080/get" -H 'apikey: john-key'
你应该收到带有以下正文的 HTTP/1.1 200 OK 响应:
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.4.0",
"X-Amzn-Trace-Id": "Root=1-664b01a6-2163c0156ed4bff51d87d877",
"X-Apisix-Consumer": "JohnDoe",
"X-Forwarded-Host": "127.0.0.1"
},
"origin": "172.19.0.1, 203.12.12.12",
"url": "http://127.0.0.1/get"
}
向路由发送另一个不带有效凭证的请求:
curl -i "http://127.0.0.1:9080/get"
你应该收到 HTTP/1.1 403 Forbidden 响应。
在 radixtree_uri_with_parameter 路由模式下动态转发请求
以下示例演示了如何使用 uri_param_* 变量提取 URL 路径的一部分,并将该值作为新请求头转发到上游服务。此示例假设 APISIX 运行在 radixtree_uri_with_parameter 路由模式下。
创建如下路由:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "httpbin",
"uri": "/anything/user/:user_id/profile",
"plugins":{
"proxy-rewrite": {
"headers": {
"set": {
"X-User-ID": "$uri_param_user_id"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
❶ 匹配请求 /anything/user/:user_id/profile,其中 user_id 是一个参数。
❷ 将 user_id 参数值分配给新请求头 X-User-ID。
向路由发送请求:
curl "http://127.0.0.1:9080/anything/user/123/profile"
你应该看到以下响应:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-68873cf5-7248f64d19d607ea50aa9735",
"X-Forwarded-Host": "127.0.0.1",
"X-User-Id": "123"
},
...
}
路由参数也可以接受 URL 编码的字符串。例如,如果你发送如下请求:
curl -i "http://127.0.0.1:9080/anything/user/123%20456/profile"
用户 ID 将被提取为 123 456:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-68873d37-7634825b20d05dee3a852cb9",
"X-Forwarded-Host": "127.0.0.1",
"X-User-Id": "123 456"
},
...
}