This is an automated email from the ASF dual-hosted git repository.

moonming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 19b788ee13 docs: correct shared plugin examples and expected results 
(#14067)
19b788ee13 is described below

commit 19b788ee13913a52e984635f464f0baf02b3f108
Author: bucketbase26 <[email protected]>
AuthorDate: Tue Nov 10 13:56:50 2026 +0530

    docs: correct shared plugin examples and expected results (#14067)
---
 docs/en/latest/plugins/ai-prompt-decorator.md |  4 +-
 docs/en/latest/plugins/ai-prompt-guard.md     |  4 +-
 docs/en/latest/plugins/ai-prompt-template.md  |  4 +-
 docs/en/latest/plugins/ai-proxy-multi.md      |  7 +-
 docs/en/latest/plugins/ai-proxy.md            | 20 +++---
 docs/en/latest/plugins/ai-rate-limiting.md    | 95 +++++++++------------------
 docs/en/latest/plugins/ai-request-rewrite.md  |  2 +-
 docs/en/latest/plugins/grpc-web.md            |  2 +
 docs/en/latest/plugins/limit-req.md           | 38 ++++++-----
 docs/en/latest/plugins/opa.md                 |  5 +-
 docs/en/latest/plugins/prometheus.md          |  8 +--
 docs/zh/latest/plugins/ai-prompt-decorator.md |  4 +-
 docs/zh/latest/plugins/ai-prompt-guard.md     |  4 +-
 docs/zh/latest/plugins/ai-prompt-template.md  |  4 +-
 docs/zh/latest/plugins/ai-proxy-multi.md      |  7 +-
 docs/zh/latest/plugins/ai-proxy.md            | 20 +++---
 docs/zh/latest/plugins/ai-rate-limiting.md    | 93 +++++++++-----------------
 docs/zh/latest/plugins/ai-request-rewrite.md  |  2 +-
 docs/zh/latest/plugins/grpc-web.md            |  2 +
 docs/zh/latest/plugins/limit-req.md           | 38 ++++++-----
 docs/zh/latest/plugins/opa.md                 |  5 +-
 docs/zh/latest/plugins/prometheus.md          |  8 +--
 22 files changed, 165 insertions(+), 211 deletions(-)

diff --git a/docs/en/latest/plugins/ai-prompt-decorator.md 
b/docs/en/latest/plugins/ai-prompt-decorator.md
index 0c4cb6cccc..ad5d02b4f9 100644
--- a/docs/en/latest/plugins/ai-prompt-decorator.md
+++ b/docs/en/latest/plugins/ai-prompt-decorator.md
@@ -58,10 +58,10 @@ See [request protocol 
detection](./ai-proxy.md#request-protocol-detection) for t
 
 ## Examples
 
-The following examples will be using OpenAI as the Upstream service provider. 
Before proceeding, create an [OpenAI account](https://openai.com) and an [API 
key](https://openai.com/blog/openai-api). You can optionally save the key to an 
environment variable as such:
+The following examples will be using OpenAI as the Upstream service provider. 
Before proceeding, create an [OpenAI account](https://openai.com) and an [API 
key](https://openai.com/blog/openai-api). Save the key to an environment 
variable, replacing the placeholder with your API key:
 
 ```shell
-export OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
+export OPENAI_API_KEY='<YOUR_OPENAI_API_KEY>'
 ```
 
 If you are working with other LLM providers, please refer to the provider's 
documentation to obtain an API key.
diff --git a/docs/en/latest/plugins/ai-prompt-guard.md 
b/docs/en/latest/plugins/ai-prompt-guard.md
index 7c621d4763..dec7d78480 100644
--- a/docs/en/latest/plugins/ai-prompt-guard.md
+++ b/docs/en/latest/plugins/ai-prompt-guard.md
@@ -61,10 +61,10 @@ When no content is selected for inspection, the request 
continues upstream. This
 
 ## Examples
 
-The following examples will be using OpenAI as the Upstream service provider. 
Before proceeding, create an [OpenAI account](https://openai.com) and an [API 
key](https://openai.com/blog/openai-api). You can optionally save the key to an 
environment variable as such:
+The following examples will be using OpenAI as the Upstream service provider. 
Before proceeding, create an [OpenAI account](https://openai.com) and an [API 
key](https://openai.com/blog/openai-api). Save the key to an environment 
variable, replacing the placeholder with your API key:
 
 ```shell
-export OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
+export OPENAI_API_KEY='<YOUR_OPENAI_API_KEY>'
 ```
 
 If you are working with other LLM providers, please refer to the provider's 
documentation to obtain an API key.
diff --git a/docs/en/latest/plugins/ai-prompt-template.md 
b/docs/en/latest/plugins/ai-prompt-template.md
index 82d1e6b60b..6c12bdde0a 100644
--- a/docs/en/latest/plugins/ai-prompt-template.md
+++ b/docs/en/latest/plugins/ai-prompt-template.md
@@ -55,10 +55,10 @@ The Plugin replaces the incoming request body with the 
selected rendered JSON te
 
 ## Examples
 
-The following examples use OpenAI as the Upstream service provider. Before 
proceeding, create an [OpenAI account](https://openai.com) and an [API 
key](https://openai.com/blog/openai-api). You can optionally save the key to an 
environment variable:
+The following examples use OpenAI as the Upstream service provider. Before 
proceeding, create an [OpenAI account](https://openai.com) and an [API 
key](https://openai.com/blog/openai-api). Save the key to an environment 
variable, replacing the placeholder with your API key:
 
 ```shell
-export OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
+export OPENAI_API_KEY='<YOUR_OPENAI_API_KEY>'
 ```
 
 If you are working with other LLM providers, please refer to the provider's 
documentation to obtain an API key.
diff --git a/docs/en/latest/plugins/ai-proxy-multi.md 
b/docs/en/latest/plugins/ai-proxy-multi.md
index ddc5472b3b..91b49ae7a0 100644
--- a/docs/en/latest/plugins/ai-proxy-multi.md
+++ b/docs/en/latest/plugins/ai-proxy-multi.md
@@ -1797,8 +1797,8 @@ The following example demonstrates how you can configure 
two [Amazon Bedrock](ht
 Save your AWS credentials to environment variables:
 
 ```shell
-export AWS_ACCESS_KEY_ID=<your-aws-access-key-id>
-export AWS_SECRET_ACCESS_KEY=<your-aws-secret-access-key>
+export AWS_ACCESS_KEY_ID='<your-aws-access-key-id>'
+export AWS_SECRET_ACCESS_KEY='<your-aws-secret-access-key>'
 ```
 
 Create a Route as such:
@@ -2203,7 +2203,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
             "weight": 0,
             "auth": {
               "header": {
-                "Authorization": "Bearer '"$AZ_OPENAI_API_KEY"'"
+                "api-key": "'"$AZ_OPENAI_API_KEY"'"
               }
             },
             "options": {
@@ -2838,7 +2838,6 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
         "kafka_topic": "test2",
         "key": "key1",
         "batch_max_size": 1
-        }
       }
     }
   }'
diff --git a/docs/en/latest/plugins/ai-proxy.md 
b/docs/en/latest/plugins/ai-proxy.md
index 3f01f84244..3d757055bd 100644
--- a/docs/en/latest/plugins/ai-proxy.md
+++ b/docs/en/latest/plugins/ai-proxy.md
@@ -211,7 +211,7 @@ The following example demonstrates how you can configure 
the API key, model, and
 Obtain the OpenAI [API key](https://openai.com/blog/openai-api) and save it to 
an environment variable:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -422,7 +422,7 @@ The following example demonstrates how you can configure 
the `ai-proxy` Plugin t
 Obtain the DeepSeek API key and save it to an environment variable:
 
 ```shell
-export DEEPSEEK_API_KEY=<your-api-key>
+export DEEPSEEK_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -636,7 +636,7 @@ The following example demonstrates how you can configure 
the `ai-proxy` Plugin t
 Obtain the Azure OpenAI API key and save it to an environment variable:
 
 ```shell
-export AZ_OPENAI_API_KEY=<your-api-key>
+export AZ_OPENAI_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -862,8 +862,8 @@ The following example demonstrates how you can configure 
the `ai-proxy` Plugin t
 Save your AWS credentials to environment variables:
 
 ```shell
-export AWS_ACCESS_KEY_ID=<your-aws-access-key-id>
-export AWS_SECRET_ACCESS_KEY=<your-aws-secret-access-key>
+export AWS_ACCESS_KEY_ID='<your-aws-access-key-id>'
+export AWS_SECRET_ACCESS_KEY='<your-aws-secret-access-key>'
 ```
 
 Create a Route and configure the `ai-proxy` Plugin as such:
@@ -1011,7 +1011,7 @@ The following example demonstrates how you can configure 
the `ai-proxy` Plugin t
 Obtain the OpenAI [API key](https://openai.com/blog/openai-api) and save it to 
an environment variable:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -1228,7 +1228,7 @@ The following example demonstrates how you can configure 
the `ai-proxy` Plugin t
 Obtain an Anthropic [API key](https://console.anthropic.com/settings/keys) and 
save it to an environment variable:
 
 ```shell
-export ANTHROPIC_API_KEY=<your-api-key>
+export ANTHROPIC_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -1442,7 +1442,7 @@ The protocol conversion is triggered automatically when 
the Route URI is set to
 Obtain an API key for your chosen OpenAI-compatible backend service and save 
it to an environment variable. This example uses OpenAI:
 
 ```shell
-export BACKEND_API_KEY=<your-api-key>
+export BACKEND_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -1659,8 +1659,8 @@ The following example demonstrates how you can proxy 
requests to different model
 The example will use OpenAI and DeepSeek as the example LLM services. Obtain 
the OpenAI and DeepSeek API keys and save them to environment variables:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
-export DEEPSEEK_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
+export DEEPSEEK_API_KEY='<your-api-key>'
 ```
 
 <Tabs
diff --git a/docs/en/latest/plugins/ai-rate-limiting.md 
b/docs/en/latest/plugins/ai-rate-limiting.md
index e5bc274b7a..522bcca25f 100644
--- a/docs/en/latest/plugins/ai-rate-limiting.md
+++ b/docs/en/latest/plugins/ai-rate-limiting.md
@@ -88,6 +88,8 @@ The `ai-rate-limiting` Plugin enforces token-based rate 
limiting for requests se
 
 The examples below demonstrate how you can configure `ai-rate-limiting` for 
different scenarios.
 
+The Plugin checks the remaining quota before forwarding a request and charges 
the tokens reported by the LLM after the response. A request can therefore 
consume more tokens than the remaining quota; later requests are rejected until 
the window resets. Quota headers on a successful response show the remaining 
quota before that response's token usage is charged.
+
 :::note
 
 You can fetch the `admin_key` from `config.yaml` and save to an environment 
variable with the following command:
@@ -98,6 +100,15 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' 
conf/config.yaml | sed 's/"/
 
 :::
 
+Before running the examples, obtain API keys for the providers you use and 
replace the placeholders below:
+
+```shell
+export OPENAI_API_KEY='<your-openai-api-key>'
+export DEEPSEEK_API_KEY='<your-deepseek-api-key>'
+```
+
+Replace `your-openai-model` in the configurations with a chat completion model 
available to your OpenAI account.
+
 ### Apply Rate Limiting with `ai-proxy`
 
 The following example demonstrates how you can use `ai-proxy` to proxy LLM 
traffic and use `ai-rate-limiting` to configure token-based rate limiting on 
the instance.
@@ -123,7 +134,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
           }
         },
         "options": {
-          "model": "gpt-35-turbo-instruct",
+          "model": "your-openai-model",
           "max_tokens": 512,
           "temperature": 1.0
         }
@@ -156,7 +167,7 @@ services:
               header:
                 Authorization: "Bearer ${OPENAI_API_KEY}"
             options:
-              model: gpt-35-turbo-instruct
+              model: your-openai-model
               max_tokens: 512
               temperature: 1.0
           ai-rate-limiting:
@@ -192,7 +203,7 @@ spec:
           header:
             Authorization: "Bearer your-api-key"
         options:
-          model: gpt-35-turbo-instruct
+          model: your-openai-model
           max_tokens: 512
           temperature: 1.0
     - name: ai-rate-limiting
@@ -250,7 +261,7 @@ spec:
               header:
                 Authorization: "Bearer your-api-key"
             options:
-              model: gpt-35-turbo-instruct
+              model: your-openai-model
               max_tokens: 512
               temperature: 1.0
         - name: ai-rate-limiting
@@ -291,7 +302,7 @@ You should receive a response similar to the following:
 ```json
 {
   ...
-  "model": "deepseek-chat",
+  "model": "your-openai-model",
   "choices": [
     {
       "index": 0,
@@ -333,7 +344,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
           }
         },
         "options": {
-          "model": "gpt-35-turbo-instruct",
+          "model": "your-openai-model",
           "max_tokens": 512,
           "temperature": 1.0
         }
@@ -384,6 +395,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
     "methods": ["POST"],
     "plugins": {
       "ai-proxy-multi": {
+        "fallback_strategy": ["rate_limiting"],
         "instances": [
           {
             "name": "deepseek-instance-1",
@@ -441,6 +453,7 @@ services:
           - POST
         plugins:
           ai-proxy-multi:
+            fallback_strategy: ["rate_limiting"]
             instances:
               - name: deepseek-instance-1
                 provider: deepseek
@@ -488,6 +501,7 @@ spec:
   plugins:
     - name: ai-proxy-multi
       config:
+        fallback_strategy: ["rate_limiting"]
         instances:
           - name: deepseek-instance-1
             provider: deepseek
@@ -557,6 +571,7 @@ spec:
         - name: ai-proxy-multi
           enable: true
           config:
+            fallback_strategy: ["rate_limiting"]
             instances:
               - name: deepseek-instance-1
                 provider: deepseek
@@ -634,11 +649,11 @@ If `deepseek-instance-1` instance rate limiting quota of 
100 tokens has been con
 
 ### Apply the Same Quota to All Instances
 
-The following example demonstrates how you can apply the same rate limiting 
quota to all LLM upstream instances in `ai-rate-limiting`.
+The following example configures a shared token quota across all LLM upstream 
instances in `ai-rate-limiting`. The top-level `limit` and `time_window` use a 
shared counter. To give instances separate quotas, configure `instances` 
instead.
 
 For demonstration and easier differentiation, you will be configuring one 
OpenAI instance and one DeepSeek instance as the upstream LLM services.
 
-Create a Route which applies a rate limiting quota of 100 total tokens for all 
instances within a 60-second window, and update with your LLM providers, 
models, API keys, and endpoints, if applicable:
+Create a Route which applies a rate limiting quota of 100 total tokens shared 
by both instances within a 60-second window, and update with your LLM 
providers, models, API keys, and endpoints, if applicable:
 
 <Tabs groupId="api">
 <TabItem value="admin-api" label="Admin API">
@@ -908,9 +923,9 @@ You should receive a response from either LLM instance, 
similar to the following
 }
 ```
 
-Since the `total_tokens` value exceeds the configured quota of `100`, the next 
request within the 60-second window is expected to be forwarded to the other 
instance.
+The example response consumes 279 total tokens, exceeding the shared quota of 
100. The next request within the same 60-second window is rejected regardless 
of which instance is selected. If your response uses fewer tokens, repeat the 
request until the shared quota is exhausted.
 
-Within the same 60-second window, send another POST request to the Route:
+Within the same window, send another POST request to the Route:
 
 ```shell
 curl -i "http://127.0.0.1:9080/anything"; -X POST \
@@ -923,63 +938,15 @@ curl -i "http://127.0.0.1:9080/anything"; -X POST \
   }'
 ```
 
-You should receive a response from the other LLM instance, similar to the 
following:
-
-```json
-{
-  ...
-  "model": "deepseek-chat",
-  "choices": [
-    {
-      "index": 0,
-      "message": {
-        "role": "assistant",
-        "content": "Sure! Newton's laws of motion are three fundamental 
principles that describe the relationship between the motion of an object and 
the forces acting on it. They were formulated by Sir Isaac Newton in the late 
17th century and are foundational to classical mechanics. Here's an explanation 
of each law:\n\n---\n\n### **1. Newton's First Law (Law of Inertia)**\n- 
**Statement**: An object will remain at rest or in uniform motion in a straight 
line unless acted upon by an ex [...]
-      },
-      "logprobs": null,
-      "finish_reason": "length"
-    }
-  ],
-  "usage": {
-    "prompt_tokens": 13,
-    "completion_tokens": 256,
-    "total_tokens": 269,
-    "prompt_tokens_details": {
-      "cached_tokens": 0
-    },
-    "prompt_cache_hit_tokens": 0,
-    "prompt_cache_miss_tokens": 13
-  },
-  "system_fingerprint": "fp_3a5770e1b4_prod0225"
-}
-```
-
-Since the `total_tokens` value exceeds the configured quota of `100`, the next 
request within the 60-second window is expected to be rejected.
-
-Within the same 60-second window, send a third POST request to the Route:
-
-```shell
-curl -i "http://127.0.0.1:9080/anything"; -X POST \
-  -H "Content-Type: application/json" \
-  -d '{
-    "messages": [
-      { "role": "system", "content": "You are a mathematician" },
-      { "role": "user", "content": "Explain Newtons laws" }
-    ]
-  }'
-```
-
-You should receive an `HTTP 429 Too Many Requests` response and observe the 
following headers:
+You should receive an `HTTP/1.1 429 Too Many Requests` response. The quota 
headers use the name of the selected instance, but the remaining quota is 
shared. For example, if `openai-instance` is selected:
 
 ```text
 X-AI-RateLimit-Limit-openai-instance: 100
 X-AI-RateLimit-Remaining-openai-instance: 0
-X-AI-RateLimit-Reset-openai-instance: 0
-X-AI-RateLimit-Limit-deepseek-instance: 100
-X-AI-RateLimit-Remaining-deepseek-instance: 0
-X-AI-RateLimit-Reset-deepseek-instance: 0
 ```
 
+The reset header reports the remaining time until the window resets. Selecting 
`deepseek-instance` does not provide a new quota.
+
 ### Configure Instance Priority and Rate Limiting
 
 The following example demonstrates how you can configure two models with 
different priorities and apply rate limiting on the instance with a higher 
priority. In the case where `fallback_strategy` is set to `["rate_limiting"]`, 
the Plugin should continue to forward requests to the low priority instance 
once the high priority instance's rate limiting quota is fully consumed.
@@ -2113,7 +2080,7 @@ These requests should match the first rule with a default 
token count of 500. Yo
 HTTP/1.1 200 OK
 ...
 X-AI-1-RateLimit-Limit: 500
-X-AI-1-RateLimit-Remaining: 499
+X-AI-1-RateLimit-Remaining: 500
 X-AI-1-RateLimit-Reset: 60
 
 HTTP/1.1 429 Too Many Requests
@@ -2144,7 +2111,7 @@ These requests should match the first rule with a custom 
token count of 10. You
 HTTP/1.1 200 OK
 ...
 X-AI-1-RateLimit-Limit: 10
-X-AI-1-RateLimit-Remaining: 9
+X-AI-1-RateLimit-Remaining: 10
 X-AI-1-RateLimit-Reset: 60
 
 HTTP/1.1 429 Too Many Requests
@@ -2174,7 +2141,7 @@ These requests should match the second rule with a token 
count of 50. You should
 HTTP/1.1 200 OK
 ...
 X-AI-2-RateLimit-Limit: 50
-X-AI-2-RateLimit-Remaining: 49
+X-AI-2-RateLimit-Remaining: 50
 X-AI-2-RateLimit-Reset: 60
 
 HTTP/1.1 429 Too Many Requests
diff --git a/docs/en/latest/plugins/ai-request-rewrite.md 
b/docs/en/latest/plugins/ai-request-rewrite.md
index 9579a8ea11..dc63161f93 100644
--- a/docs/en/latest/plugins/ai-request-rewrite.md
+++ b/docs/en/latest/plugins/ai-request-rewrite.md
@@ -71,7 +71,7 @@ The examples below demonstrate how you can configure 
`ai-request-rewrite` for di
 The examples use OpenAI as the LLM service. To follow along, obtain an OpenAI 
[API key](https://openai.com/blog/openai-api) and save it to an environment 
variable:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
 ```
 
 :::note
diff --git a/docs/en/latest/plugins/grpc-web.md 
b/docs/en/latest/plugins/grpc-web.md
index f1c55663ce..b61b07cbfe 100644
--- a/docs/en/latest/plugins/grpc-web.md
+++ b/docs/en/latest/plugins/grpc-web.md
@@ -107,6 +107,8 @@ docker run -d \
   moul/grpcbin
 ```
 
+The Route below uses `127.0.0.1:9000` as the upstream address and assumes 
APISIX runs on the Docker host. If APISIX runs in a container, connect both 
containers to the same [user-defined Docker 
network](https://docs.docker.com/engine/network/drivers/bridge/) and use 
`grpcbin:9000` in the Route instead. Inside the APISIX container, `127.0.0.1` 
refers to APISIX itself; Docker resolves `grpcbin` on the shared network.
+
 #### Generate gRPC-Web Client Code
 
 Download the Protocol Buffer definition `hello.proto`:
diff --git a/docs/en/latest/plugins/limit-req.md 
b/docs/en/latest/plugins/limit-req.md
index eaf771ea3a..988fee24b8 100644
--- a/docs/en/latest/plugins/limit-req.md
+++ b/docs/en/latest/plugins/limit-req.md
@@ -49,13 +49,13 @@ The `limit-req` Plugin supports two modes of rate limiting:
 
 | Name | Type | Required | Default | Valid values | Description |
 |------|------|----------|---------|--------------|-------------|
-| rate | number | True | | > 0 | The maximum number of requests allowed per 
second. Requests exceeding the rate and below burst will be delayed. |
-| burst | number | True | | >= 0 | The number of requests allowed to be 
delayed per second for throttling. Requests exceeding the rate and burst will 
get rejected. |
+| rate | number | True | | > 0 | The rate at which requests are admitted, in 
requests per second. Excess requests within the `burst` capacity are delayed 
unless `nodelay` is `true`. |
+| burst | number | True | | >= 0 | The maximum number of excess requests 
allowed above the configured `rate`. This is a burst capacity, not a per-second 
quota. Requests exceeding this capacity are rejected. |
 | key_type | string | False | var | ["var", "var_combination"] | The type of 
key. If the `key_type` is `var`, the `key` is interpreted as a variable. If the 
`key_type` is `var_combination`, the `key` is interpreted as a combination of 
variables. |
 | key | string | True | | | The key to count requests by. If the `key_type` is 
`var`, the `key` is interpreted as a variable. The variable does not need to be 
prefixed by a dollar sign (`$`). If the `key_type` is `var_combination`, the 
`key` is interpreted as a combination of variables. All variables should be 
prefixed by dollar signs (`$`). For example, to configure the `key` to use a 
combination of two request headers `custom-a` and `custom-b`, the `key` should 
be configured as `$http_ [...]
 | rejected_code | integer | False | 503 | [200,...,599] | The HTTP status code 
returned when a request is rejected for exceeding the threshold. |
 | rejected_msg | string | False | | non-empty | The response body returned 
when a request is rejected for exceeding the threshold. |
-| nodelay | boolean | False | false | | If true, do not delay requests within 
the burst threshold. |
+| nodelay | boolean | False | false | | If true, admit requests within the 
`burst` capacity without delay. Excess requests still consume burst capacity 
and are rejected when it is exhausted. |
 | allow_degradation | boolean | False | false | | If true, allow APISIX to 
continue handling requests without the Plugin when the Plugin or its 
dependencies become unavailable. |
 | policy | string | False | local | ["local", "redis", "redis-cluster"] | The 
policy for rate limiting counter. If it is `local`, the counter is stored in 
memory locally. If it is `redis`, the counter is stored on a Redis instance. If 
it is `redis-cluster`, the counter is stored in a Redis cluster. |
 | redis_host | string | False | | | The address of the Redis node. Required 
when `policy` is `redis`. |
@@ -305,7 +305,7 @@ curl -i "http://127.0.0.1:9080/get";
 
 You should see an `HTTP/1.1 200 OK` response.
 
-The request has consumed all the quota allowed for the time window. If you 
send the request again within the same second, you should receive an `HTTP/1.1 
429 Too Many Requests` response, indicating the request surpasses the quota 
threshold.
+With `rate` set to 1 and `burst` set to 0, a second request arriving less than 
one second after the first is rejected with `HTTP/1.1 429 Too Many Requests`. 
The leaky bucket drains continuously; it does not reset at the start of each 
second.
 
 ### Implement API Throttling
 
@@ -501,22 +501,23 @@ kubectl apply -f limit-req-ic.yaml
 
 ❶ `burst`: allow for 1 request exceeding the `rate` to be delayed for 
processing.
 
-Generate three requests to the Route:
+Wait for any previous burst to drain, then send three requests to the Route in 
parallel:
 
 ```shell
-resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get"; -o /dev/null -s 
-w "%{http_code}\n") && \
+sleep 2
+resp=$(seq 3 | xargs -P 3 -I{} curl "http://127.0.0.1:9080/get"; -o /dev/null 
-s -w "%{http_code}\n") && \
   count_200=$(echo "$resp" | grep "200" | wc -l) && \
   count_429=$(echo "$resp" | grep "429" | wc -l) && \
   echo "200 responses: $count_200 ; 429 responses: $count_429"
 ```
 
-You are likely to see that all three requests are successful:
+With an initially empty bucket and all three requests arriving together, one 
request proceeds immediately, one is delayed by about one second, and one is 
rejected:
 
 ```text
-200 responses: 3 ; 429 responses: 0
+200 responses: 2 ; 429 responses: 1
 ```
 
-To see the effect without `burst`, update `burst` to 0 or set `nodelay` to 
`true` as follows:
+To admit the excess request without delaying it, keep `burst` set to 1 and set 
`nodelay` to `true`:
 
 <Tabs
 groupId="api"
@@ -557,7 +558,7 @@ services:
         plugins:
           limit-req:
             rate: 1
-            burst: 1  # alternatively, set burst to 0
+            burst: 1
             key: remote_addr
             rejected_code: 429
             policy: local
@@ -603,7 +604,7 @@ spec:
     - name: limit-req
       config:
         rate: 1
-        burst: 1  # alternatively, set burst to 0
+        burst: 1
         key: remote_addr
         rejected_code: 429
         policy: local
@@ -635,7 +636,7 @@ spec:
         - name: limit-req
           config:
             rate: 1
-            burst: 1  # alternatively, set burst to 0
+            burst: 1
             key: remote_addr
             rejected_code: 429
             policy: local
@@ -656,21 +657,26 @@ kubectl apply -f limit-req-ic.yaml
 
 </Tabs>
 
-Generate three requests to the Route again:
+Wait for the bucket to drain, then send three requests in parallel again:
 
 ```shell
-resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get"; -o /dev/null -s 
-w "%{http_code}\n") && \
+sleep 2
+resp=$(seq 3 | xargs -P 3 -I{} curl "http://127.0.0.1:9080/get"; -o /dev/null 
-s -w "%{http_code}\n") && \
   count_200=$(echo "$resp" | grep "200" | wc -l) && \
   count_429=$(echo "$resp" | grep "429" | wc -l) && \
   echo "200 responses: $count_200 ; 429 responses: $count_429"
 ```
 
-You should see a response similar to the following, showing requests 
surpassing the rate have been rejected:
+The expected counts are the same, but both accepted requests now proceed 
without a throttling delay:
 
 ```text
-200 responses: 1 ; 429 responses: 2
+200 responses: 2 ; 429 responses: 1
 ```
 
+The counts can vary if requests arrive far enough apart for the bucket to 
drain. Sending requests serially can hide the effect of `burst`, because each 
delayed request gives the bucket time to drain before the next request arrives.
+
+To reject excess requests instead of allowing a burst, set `burst` to 0. For 
three requests arriving together at `rate: 1`, one succeeds and two are 
rejected, regardless of `nodelay`.
+
 ### Apply Rate Limiting by Remote Address and Consumer Name
 
 The following example demonstrates the rate limiting of requests by a 
combination of variables, `remote_addr` and `consumer_name`.
diff --git a/docs/en/latest/plugins/opa.md b/docs/en/latest/plugins/opa.md
index fc702355ee..f242b8a9ca 100644
--- a/docs/en/latest/plugins/opa.md
+++ b/docs/en/latest/plugins/opa.md
@@ -910,7 +910,10 @@ role_permissions := {
 
 # Get JWT authorization token
 bearer_token := t if {
-  t := input.request.headers.authorization
+  parts := split(input.request.headers.authorization, " ")
+  count(parts) == 2
+  lower(parts[0]) == "bearer"
+  t := parts[1]
 }
 
 # Decode the token to get role and permission
diff --git a/docs/en/latest/plugins/prometheus.md 
b/docs/en/latest/plugins/prometheus.md
index 632ae25dd1..6cf50e6dbd 100644
--- a/docs/en/latest/plugins/prometheus.md
+++ b/docs/en/latest/plugins/prometheus.md
@@ -586,7 +586,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
       "checks": {
         "active": {
           "timeout": 5,
-          "http_path": "/status",
+          "http_path": "/status/200",
           "healthy": {
             "interval": 2,
             "successes": 1
@@ -623,11 +623,11 @@ You should see an output similar to the following:
 ```text
 # HELP apisix_upstream_status upstream status from health check
 # TYPE apisix_upstream_status gauge
-apisix_upstream_status{name="/apisix/routes/1",ip="54.237.103.220",port="80"} 1
-apisix_upstream_status{name="/apisix/routes/1",ip="127.0.0.1",port="20001"} 0
+apisix_upstream_status{name="/apisix/routes/prometheus-route",ip="54.237.103.220",port="80"}
 1
+apisix_upstream_status{name="/apisix/routes/prometheus-route",ip="127.0.0.1",port="20001"}
 0
 ```
 
-This shows that the upstream node `httpbin.org:80` is healthy and the upstream 
node `127.0.0.1:20001` is unhealthy.
+This shows that the upstream node `httpbin.org:80` is healthy and the upstream 
node `127.0.0.1:20001` is unhealthy, assuming no service is listening on port 
`20001`. HTTPBin returns `200` for `/status/200`. The resolved IP address can 
differ, and health checks need time to update the node statuses.
 
 ### Add Extra Labels for Metrics
 
diff --git a/docs/zh/latest/plugins/ai-prompt-decorator.md 
b/docs/zh/latest/plugins/ai-prompt-decorator.md
index 92b37f6ada..0362f73feb 100644
--- a/docs/zh/latest/plugins/ai-prompt-decorator.md
+++ b/docs/zh/latest/plugins/ai-prompt-decorator.md
@@ -57,10 +57,10 @@ import TabItem from '@theme/TabItem';
 
 ## 示例
 
-以下示例将使用 OpenAI 作为上游服务提供商。在开始之前,请创建一个 [OpenAI 账户](https://openai.com) 和一个 [API 
密钥](https://openai.com/blog/openai-api)。你可以选择将密钥保存到环境变量中:
+以下示例将使用 OpenAI 作为上游服务提供商。在开始之前,请创建一个 [OpenAI 账户](https://openai.com) 和一个 [API 
密钥](https://openai.com/blog/openai-api)。请将密钥保存到环境变量中,并将占位符替换为你的 API 密钥:
 
 ```shell
-export OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
+export OPENAI_API_KEY='<YOUR_OPENAI_API_KEY>'
 ```
 
 如果你使用的是其他 LLM 提供商,请参阅该提供商的文档以获取 API 密钥。
diff --git a/docs/zh/latest/plugins/ai-prompt-guard.md 
b/docs/zh/latest/plugins/ai-prompt-guard.md
index 34224e58a1..5a97a33be4 100644
--- a/docs/zh/latest/plugins/ai-prompt-guard.md
+++ b/docs/zh/latest/plugins/ai-prompt-guard.md
@@ -60,10 +60,10 @@ import TabItem from '@theme/TabItem';
 
 ## 使用示例
 
-以下示例将使用 OpenAI 作为上游服务提供商。在继续之前,请创建一个 [OpenAI 账户](https://openai.com)和一个 [API 
密钥](https://openai.com/blog/openai-api)。你可以选择将密钥保存到环境变量中:
+以下示例将使用 OpenAI 作为上游服务提供商。在继续之前,请创建一个 [OpenAI 账户](https://openai.com)和一个 [API 
密钥](https://openai.com/blog/openai-api)。请将密钥保存到环境变量中,并将占位符替换为你的 API 密钥:
 
 ```shell
-export OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
+export OPENAI_API_KEY='<YOUR_OPENAI_API_KEY>'
 ```
 
 如果你使用其他 LLM 提供商,请参阅提供商的文档以获取 API 密钥。
diff --git a/docs/zh/latest/plugins/ai-prompt-template.md 
b/docs/zh/latest/plugins/ai-prompt-template.md
index e1db666190..3b87e7d120 100644
--- a/docs/zh/latest/plugins/ai-prompt-template.md
+++ b/docs/zh/latest/plugins/ai-prompt-template.md
@@ -54,10 +54,10 @@ import TabItem from '@theme/TabItem';
 
 ## 使用示例
 
-以下示例使用 OpenAI 作为上游服务提供商。开始之前,请先创建一个 [OpenAI 账户](https://openai.com)和一个 [API 
密钥](https://openai.com/blog/openai-api)。你可以选择将密钥保存到环境变量中:
+以下示例使用 OpenAI 作为上游服务提供商。开始之前,请先创建一个 [OpenAI 账户](https://openai.com)和一个 [API 
密钥](https://openai.com/blog/openai-api)。请将密钥保存到环境变量中,并将占位符替换为你的 API 密钥:
 
 ```shell
-export OPENAI_API_KEY=<YOUR_OPENAI_API_KEY>
+export OPENAI_API_KEY='<YOUR_OPENAI_API_KEY>'
 ```
 
 如果你正在使用其他 LLM 提供商,请参阅该提供商的文档以获取 API 密钥。
diff --git a/docs/zh/latest/plugins/ai-proxy-multi.md 
b/docs/zh/latest/plugins/ai-proxy-multi.md
index 413da5f779..2e69b9e17a 100644
--- a/docs/zh/latest/plugins/ai-proxy-multi.md
+++ b/docs/zh/latest/plugins/ai-proxy-multi.md
@@ -1772,8 +1772,8 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 将您的 AWS 凭证保存到环境变量:
 
 ```shell
-export AWS_ACCESS_KEY_ID=<your-aws-access-key-id>
-export AWS_SECRET_ACCESS_KEY=<your-aws-secret-access-key>
+export AWS_ACCESS_KEY_ID='<your-aws-access-key-id>'
+export AWS_SECRET_ACCESS_KEY='<your-aws-secret-access-key>'
 ```
 
 创建路由:
@@ -1989,7 +1989,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
             "weight": 0,
             "auth": {
               "header": {
-                "Authorization": "Bearer '"$AZ_OPENAI_API_KEY"'"
+                "api-key": "'"$AZ_OPENAI_API_KEY"'"
               }
             },
             "options": {
@@ -2549,7 +2549,6 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
         "kafka_topic": "test2",
         "key": "key1",
         "batch_max_size": 1
-        }
       }
     }
   }'
diff --git a/docs/zh/latest/plugins/ai-proxy.md 
b/docs/zh/latest/plugins/ai-proxy.md
index 9d9261babc..7e77a1f6a9 100644
--- a/docs/zh/latest/plugins/ai-proxy.md
+++ b/docs/zh/latest/plugins/ai-proxy.md
@@ -187,7 +187,7 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' 
conf/config.yaml | sed 's/"/
 获取 OpenAI [API 密钥](https://openai.com/blog/openai-api)并保存到环境变量:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -398,7 +398,7 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 获取 DeepSeek API 密钥并保存到环境变量:
 
 ```shell
-export DEEPSEEK_API_KEY=<your-api-key>
+export DEEPSEEK_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -612,7 +612,7 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 获取 Azure OpenAI API 密钥并保存到环境变量:
 
 ```shell
-export AZ_OPENAI_API_KEY=<your-api-key>
+export AZ_OPENAI_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -838,8 +838,8 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 将您的 AWS 凭证保存到环境变量:
 
 ```shell
-export AWS_ACCESS_KEY_ID=<your-aws-access-key-id>
-export AWS_SECRET_ACCESS_KEY=<your-aws-secret-access-key>
+export AWS_ACCESS_KEY_ID='<your-aws-access-key-id>'
+export AWS_SECRET_ACCESS_KEY='<your-aws-secret-access-key>'
 ```
 
 创建路由并配置 `ai-proxy` 插件:
@@ -987,7 +987,7 @@ curl "http://127.0.0.1:9080/v1/responses"; -X POST \
 获取 OpenAI [API 密钥](https://openai.com/blog/openai-api)并保存到环境变量:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -1204,7 +1204,7 @@ curl "http://127.0.0.1:9080/embeddings"; -X POST \
 获取 Anthropic [API 密钥](https://console.anthropic.com/settings/keys)并保存到环境变量:
 
 ```shell
-export ANTHROPIC_API_KEY=<your-api-key>
+export ANTHROPIC_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -1416,7 +1416,7 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 获取你选择的 OpenAI 兼容后端服务的 API 密钥并保存到环境变量。此示例使用 OpenAI:
 
 ```shell
-export BACKEND_API_KEY=<your-api-key>
+export BACKEND_API_KEY='<your-api-key>'
 ```
 
 <Tabs
@@ -1631,8 +1631,8 @@ curl "http://127.0.0.1:9080/v1/messages"; -X POST \
 此示例将使用 OpenAI 和 DeepSeek 作为示例 LLM 服务。获取 OpenAI 和 DeepSeek API 密钥并保存到环境变量:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
-export DEEPSEEK_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
+export DEEPSEEK_API_KEY='<your-api-key>'
 ```
 
 <Tabs
diff --git a/docs/zh/latest/plugins/ai-rate-limiting.md 
b/docs/zh/latest/plugins/ai-rate-limiting.md
index da72daf65e..3331d2e15b 100644
--- a/docs/zh/latest/plugins/ai-rate-limiting.md
+++ b/docs/zh/latest/plugins/ai-rate-limiting.md
@@ -65,6 +65,8 @@ import TabItem from '@theme/TabItem';
 
 以下示例演示了如何为不同场景配置 `ai-rate-limiting`。
 
+插件在转发请求前检查剩余配额,并在响应后扣除 LLM 
报告的令牌用量。因此,一个请求可能消耗超过剩余配额的令牌;配额耗尽后,后续请求会被拒绝,直到时间窗口重置。成功响应中的配额头部显示扣除此响应的令牌用量之前的剩余配额。
+
 :::note
 
 你可以使用以下命令从 `config.yaml` 获取 `admin_key` 并保存到环境变量中:
@@ -75,6 +77,15 @@ admin_key=$(yq '.deployment.admin.admin_key[0].key' 
conf/config.yaml | sed 's/"/
 
 :::
 
+运行示例之前,请获取所用提供商的 API 密钥,并替换以下占位符:
+
+```shell
+export OPENAI_API_KEY='<your-openai-api-key>'
+export DEEPSEEK_API_KEY='<your-deepseek-api-key>'
+```
+
+请将配置中的 `your-openai-model` 替换为你的 OpenAI 账户可用的聊天补全模型。
+
 ### 与 `ai-proxy` 一起应用速率限制
 
 以下示例演示了如何使用 `ai-proxy` 代理 LLM 流量,并使用 `ai-rate-limiting` 在实例上配置基于令牌的速率限制。
@@ -100,7 +111,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
           }
         },
         "options": {
-          "model": "gpt-35-turbo-instruct",
+          "model": "your-openai-model",
           "max_tokens": 512,
           "temperature": 1.0
         }
@@ -133,7 +144,7 @@ services:
               header:
                 Authorization: "Bearer ${OPENAI_API_KEY}"
             options:
-              model: gpt-35-turbo-instruct
+              model: your-openai-model
               max_tokens: 512
               temperature: 1.0
           ai-rate-limiting:
@@ -169,7 +180,7 @@ spec:
           header:
             Authorization: "Bearer your-api-key"
         options:
-          model: gpt-35-turbo-instruct
+          model: your-openai-model
           max_tokens: 512
           temperature: 1.0
     - name: ai-rate-limiting
@@ -227,7 +238,7 @@ spec:
               header:
                 Authorization: "Bearer your-api-key"
             options:
-              model: gpt-35-turbo-instruct
+              model: your-openai-model
               max_tokens: 512
               temperature: 1.0
         - name: ai-rate-limiting
@@ -268,7 +279,7 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 ```json
 {
   ...
-  "model": "deepseek-chat",
+  "model": "your-openai-model",
   "choices": [
     {
       "index": 0,
@@ -304,6 +315,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
     "methods": ["POST"],
     "plugins": {
       "ai-proxy-multi": {
+        "fallback_strategy": ["rate_limiting"],
         "instances": [
           {
             "name": "deepseek-instance-1",
@@ -361,6 +373,7 @@ services:
           - POST
         plugins:
           ai-proxy-multi:
+            fallback_strategy: ["rate_limiting"]
             instances:
               - name: deepseek-instance-1
                 provider: deepseek
@@ -408,6 +421,7 @@ spec:
   plugins:
     - name: ai-proxy-multi
       config:
+        fallback_strategy: ["rate_limiting"]
         instances:
           - name: deepseek-instance-1
             provider: deepseek
@@ -477,6 +491,7 @@ spec:
         - name: ai-proxy-multi
           enable: true
           config:
+            fallback_strategy: ["rate_limiting"]
             instances:
               - name: deepseek-instance-1
                 provider: deepseek
@@ -554,11 +569,11 @@ curl "http://127.0.0.1:9080/anything"; -X POST \
 
 ### 对所有实例应用相同配额
 
-以下示例演示了如何对 `ai-rate-limiting` 中的所有 LLM 上游实例应用相同的速率限制配额。
+以下示例在 `ai-rate-limiting` 中为所有 LLM 上游实例配置共享令牌配额。顶层的 `limit` 和 `time_window` 
使用共享计数器。要为实例设置独立配额,请配置 `instances`。
 
 为了演示和更容易区分,你将配置一个 OpenAI 实例和一个 DeepSeek 实例作为上游 LLM 服务。
 
-创建一个路由,对所有实例在 60 秒窗口内应用 100 个总令牌的速率限制配额,并更新你的 LLM 提供商、模型、API 密钥和端点(如适用):
+创建一个路由,在 60 秒窗口内为两个实例配置共享的 100 个总令牌配额,并更新你的 LLM 提供商、模型、API 密钥和端点(如适用):
 
 <Tabs groupId="api">
 <TabItem value="admin-api" label="Admin API">
@@ -828,9 +843,9 @@ curl -i "http://127.0.0.1:9080/anything"; -X POST \
 }
 ```
 
-由于 `total_tokens` 值超过了配置的 `100` 配额,预期在 60 秒窗口内的下一个请求将被转发到另一个实例。
+示例响应消耗了 279 个总令牌,超过了共享配额 100。在同一个 60 
秒窗口内,无论选择哪个实例,下一个请求都会被拒绝。如果你的响应消耗的令牌较少,请重复发送请求,直到共享配额耗尽。
 
-在同一个 60 秒窗口内,向路由发送另一个 POST 请求:
+在同一个时间窗口内,向路由发送另一个 POST 请求:
 
 ```shell
 curl -i "http://127.0.0.1:9080/anything"; -X POST \
@@ -843,63 +858,15 @@ curl -i "http://127.0.0.1:9080/anything"; -X POST \
   }'
 ```
 
-你应该收到来自另一个 LLM 实例的响应,类似以下内容:
-
-```json
-{
-  ...
-  "model": "deepseek-chat",
-  "choices": [
-    {
-      "index": 0,
-      "message": {
-        "role": "assistant",
-        "content": "Sure! Newton's laws of motion are three fundamental 
principles that describe the relationship between the motion of an object and 
the forces acting on it. They were formulated by Sir Isaac Newton in the late 
17th century and are foundational to classical mechanics. Here's an explanation 
of each law:\n\n---\n\n### **1. Newton's First Law (Law of Inertia)**\n- 
**Statement**: An object will remain at rest or in uniform motion in a straight 
line unless acted upon by an ex [...]
-      },
-      "logprobs": null,
-      "finish_reason": "length"
-    }
-  ],
-  "usage": {
-    "prompt_tokens": 13,
-    "completion_tokens": 256,
-    "total_tokens": 269,
-    "prompt_tokens_details": {
-      "cached_tokens": 0
-    },
-    "prompt_cache_hit_tokens": 0,
-    "prompt_cache_miss_tokens": 13
-  },
-  "system_fingerprint": "fp_3a5770e1b4_prod0225"
-}
-```
-
-由于 `total_tokens` 值超过了配置的 `100` 配额,预期在 60 秒窗口内的下一个请求将被拒绝。
-
-在同一个 60 秒窗口内,向路由发送第三个 POST 请求:
-
-```shell
-curl -i "http://127.0.0.1:9080/anything"; -X POST \
-  -H "Content-Type: application/json" \
-  -d '{
-    "messages": [
-      { "role": "system", "content": "You are a mathematician" },
-      { "role": "user", "content": "Explain Newtons laws" }
-    ]
-  }'
-```
-
-你应该收到 `HTTP 429 Too Many Requests` 响应并观察到以下头部:
+你应该收到 `HTTP/1.1 429 Too Many Requests` 响应。配额头部使用所选实例的名称,但剩余配额是共享的。例如,选择 
`openai-instance` 时:
 
 ```text
 X-AI-RateLimit-Limit-openai-instance: 100
 X-AI-RateLimit-Remaining-openai-instance: 0
-X-AI-RateLimit-Reset-openai-instance: 0
-X-AI-RateLimit-Limit-deepseek-instance: 100
-X-AI-RateLimit-Remaining-deepseek-instance: 0
-X-AI-RateLimit-Reset-deepseek-instance: 0
 ```
 
+重置头部表示距离时间窗口重置的剩余时间。选择 `deepseek-instance` 不会获得新的配额。
+
 ### 配置实例优先级和速率限制
 
 以下示例演示了如何配置两个具有不同优先级的模型,并对具有较高优先级的实例应用速率限制。在 `fallback_strategy` 设置为 
`["rate_limiting"]` 的情况下,一旦高优先级实例的速率限制配额完全消耗,插件应继续将请求转发到低优先级实例。
@@ -2033,7 +2000,7 @@ curl "http://127.0.0.1:9080/anything"; -i -X POST \
 HTTP/1.1 200 OK
 ...
 X-AI-1-RateLimit-Limit: 500
-X-AI-1-RateLimit-Remaining: 499
+X-AI-1-RateLimit-Remaining: 500
 X-AI-1-RateLimit-Reset: 60
 
 HTTP/1.1 429 Too Many Requests
@@ -2064,7 +2031,7 @@ curl "http://127.0.0.1:9080/anything"; -i -X POST \
 HTTP/1.1 200 OK
 ...
 X-AI-1-RateLimit-Limit: 10
-X-AI-1-RateLimit-Remaining: 9
+X-AI-1-RateLimit-Remaining: 10
 X-AI-1-RateLimit-Reset: 60
 
 HTTP/1.1 429 Too Many Requests
@@ -2094,7 +2061,7 @@ curl "http://127.0.0.1:9080/anything"; -i -X POST \
 HTTP/1.1 200 OK
 ...
 X-AI-2-RateLimit-Limit: 50
-X-AI-2-RateLimit-Remaining: 49
+X-AI-2-RateLimit-Remaining: 50
 X-AI-2-RateLimit-Reset: 60
 
 HTTP/1.1 429 Too Many Requests
diff --git a/docs/zh/latest/plugins/ai-request-rewrite.md 
b/docs/zh/latest/plugins/ai-request-rewrite.md
index f06697a3e9..eaa8246eea 100644
--- a/docs/zh/latest/plugins/ai-request-rewrite.md
+++ b/docs/zh/latest/plugins/ai-request-rewrite.md
@@ -70,7 +70,7 @@ import TabItem from '@theme/TabItem';
 示例使用 OpenAI 作为 LLM 服务。请先获取 OpenAI [API 
密钥](https://openai.com/blog/openai-api)并将其保存到环境变量:
 
 ```shell
-export OPENAI_API_KEY=<your-api-key>
+export OPENAI_API_KEY='<your-api-key>'
 ```
 
 :::note
diff --git a/docs/zh/latest/plugins/grpc-web.md 
b/docs/zh/latest/plugins/grpc-web.md
index 7e613f9b4d..544e5ec804 100644
--- a/docs/zh/latest/plugins/grpc-web.md
+++ b/docs/zh/latest/plugins/grpc-web.md
@@ -106,6 +106,8 @@ docker run -d \
   moul/grpcbin
 ```
 
+下面的路由使用 `127.0.0.1:9000` 作为上游地址,并假设 APISIX 运行在 Docker 宿主机上。如果 APISIX 
运行在容器中,请将两个容器连接到同一个[用户自定义 Docker 
网络](https://docs.docker.com/engine/network/drivers/bridge/),并在路由中使用 
`grpcbin:9000`。在 APISIX 容器内,`127.0.0.1` 指向 APISIX 自身;Docker 会在共享网络中解析 `grpcbin`。
+
 #### 生成 gRPC-Web 客户端代码
 
 下载 Protocol Buffer 定义文件 `hello.proto`:
diff --git a/docs/zh/latest/plugins/limit-req.md 
b/docs/zh/latest/plugins/limit-req.md
index 40a3e8aaaf..587f3ecc6b 100644
--- a/docs/zh/latest/plugins/limit-req.md
+++ b/docs/zh/latest/plugins/limit-req.md
@@ -49,13 +49,13 @@ import TabItem from '@theme/TabItem';
 
 | 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
 |------|------|----------|---------|--------------|-------------|
-| rate | number | 是 | | > 0 | 每秒允许的最大请求数。超过速率且低于突发的请求将被延迟。|
-| burst | number | 是 | | >= 0 | 每秒允许延迟的请求数,以进行节流。超过速率和突发的请求将被拒绝。|
+| rate | number | 是 | | > 0 | 允许请求通过的速率,单位为请求数/秒。超过速率但在 `burst` 容量内的请求会被延迟,除非 
`nodelay` 为 `true`。|
+| burst | number | 是 | | >= 0 | 超过配置的 `rate` 
时允许的最大额外请求数。这是突发容量,不是每秒配额。超过此容量的请求会被拒绝。|
 | key_type | string | 否 | var | ["var", "var_combination"] | key 的类型。如果 
`key_type` 为 `var`,则 `key` 将被解释为变量。如果 `key_type` 为 `var_combination`,则 `key` 
将被解释为变量的组合。|
 | key | string | 是 | | | 用于计数请求的 key。如果 `key_type` 为 `var`,则 `key` 
将被解释为变量。变量不需要以美元符号(`$`)为前缀。如果 `key_type` 为 `var_combination`,则 `key` 
会被解释为变量的组合。所有变量都应该以美元符号(`$`)为前缀。例如,要配置 `key` 使用两个请求头 `custom-a` 和 `custom-b` 
的组合,则 `key` 应该配置为 `$http_custom_a $http_custom_b`。|
 | rejected_code | integer | 否 | 503 | [200,...,599] | 请求因超出阈值而被拒绝时返回的 HTTP 
状态代码。|
 | rejected_msg | string | 否 | | 非空 | 请求因超出阈值而被拒绝时返回的响应主体。|
-| nodelay | boolean | 否 | false | | 如果为 true,则不延迟突发阈值内的请求。|
+| nodelay | boolean | 否 | false | | 如果为 `true`,则允许 `burst` 
容量内的请求立即通过。额外请求仍会占用突发容量,容量耗尽时后续请求会被拒绝。|
 | allow_degradation | boolean | 否 | false | | 如果为 true,则允许 APISIX 
在插件或其依赖项不可用时继续处理没有插件的请求。|
 | policy | string | 否 | local | ["local", "redis", "redis-cluster"] | 
速率限制计数器的策略。如果是 `local`,则计数器存储在本地内存中。如果是 `redis`,则计数器存储在 Redis 实例上。如果是 
`redis-cluster`,则计数器存储在 Redis 集群中。|
 | redis_host | string | 否 | | | Redis 节点的地址。当 `policy` 为 `redis` 时必填。|
@@ -305,7 +305,7 @@ curl -i "http://127.0.0.1:9080/get";
 
 你应该会看到一个 `HTTP/1.1 200 OK` 响应。
 
-该请求已消耗了时间窗口允许的所有配额。如果你在同一秒内再次发送请求,你应该会收到 `HTTP/1.1 429 Too Many Requests` 
响应,表示请求超出了配额阈值。
+当 `rate` 为 1 且 `burst` 为 0 时,如果第二个请求在第一个请求到达后不到一秒内到达,它会被拒绝,并返回 `HTTP/1.1 429 
Too Many Requests`。漏桶会持续排空,不会在每秒开始时重置。
 
 ### 实现 API 节流
 
@@ -501,22 +501,23 @@ kubectl apply -f limit-req-ic.yaml
 
 ❶ `burst`:允许 1 个超过 `rate` 的请求延迟处理。
 
-生成三个对路由的请求:
+等待之前的突发请求排空,然后并行向路由发送三个请求:
 
 ```shell
-resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get"; -o /dev/null -s 
-w "%{http_code}\n") && \
+sleep 2
+resp=$(seq 3 | xargs -P 3 -I{} curl "http://127.0.0.1:9080/get"; -o /dev/null 
-s -w "%{http_code}\n") && \
   count_200=$(echo "$resp" | grep "200" | wc -l) && \
   count_429=$(echo "$resp" | grep "429" | wc -l) && \
   echo "200 responses: $count_200 ; 429 responses: $count_429"
 ```
 
-你可能会看到所有三个请求都成功:
+当漏桶初始为空且三个请求同时到达时,一个请求立即通过,一个请求延迟约一秒,另一个请求被拒绝:
 
 ```text
-200 responses: 3 ; 429 responses: 0
+200 responses: 2 ; 429 responses: 1
 ```
 
-要查看没有 `burst` 的效果,请将 `burst` 更新为 0 或将 `nodelay` 设置为 `true`,如下所示:
+要让额外请求立即通过,请保持 `burst` 为 1,并将 `nodelay` 设置为 `true`:
 
 <Tabs
 groupId="api"
@@ -557,7 +558,7 @@ services:
         plugins:
           limit-req:
             rate: 1
-            burst: 1  # alternatively, set burst to 0
+            burst: 1
             key: remote_addr
             rejected_code: 429
             policy: local
@@ -603,7 +604,7 @@ spec:
     - name: limit-req
       config:
         rate: 1
-        burst: 1  # alternatively, set burst to 0
+        burst: 1
         key: remote_addr
         rejected_code: 429
         policy: local
@@ -635,7 +636,7 @@ spec:
         - name: limit-req
           config:
             rate: 1
-            burst: 1  # alternatively, set burst to 0
+            burst: 1
             key: remote_addr
             rejected_code: 429
             policy: local
@@ -656,21 +657,26 @@ kubectl apply -f limit-req-ic.yaml
 
 </Tabs>
 
-再次向路由生成三个请求:
+等待漏桶排空,然后再次并行发送三个请求:
 
 ```shell
-resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/get"; -o /dev/null -s 
-w "%{http_code}\n") && \
+sleep 2
+resp=$(seq 3 | xargs -P 3 -I{} curl "http://127.0.0.1:9080/get"; -o /dev/null 
-s -w "%{http_code}\n") && \
   count_200=$(echo "$resp" | grep "200" | wc -l) && \
   count_429=$(echo "$resp" | grep "429" | wc -l) && \
   echo "200 responses: $count_200 ; 429 responses: $count_429"
 ```
 
-你应该会看到类似以下内容的响应,表明超出速率的请求已被拒绝:
+预期响应数量不变,但两个被接受的请求现在都不再受到节流延迟:
 
 ```text
-200 responses: 1 ; 429 responses: 2
+200 responses: 2 ; 429 responses: 1
 ```
 
+如果请求到达的间隔足以让漏桶排空,响应数量可能不同。串行发送请求可能掩盖 `burst` 的作用,因为每个延迟的请求都会让漏桶有时间在下一个请求到达之前排空。
+
+要拒绝额外请求而不允许突发,请将 `burst` 设置为 0。在 `rate: 1` 时,三个同时到达的请求中一个成功、两个被拒绝,与 `nodelay` 
的值无关。
+
 ### 按远程地址和消费者名称应用速率限制
 
 以下示例演示了通过变量组合 `remote_addr` 和 `consumer_name` 来限制请求的速率。
diff --git a/docs/zh/latest/plugins/opa.md b/docs/zh/latest/plugins/opa.md
index 0e9c1e0d56..ff45e95ef5 100644
--- a/docs/zh/latest/plugins/opa.md
+++ b/docs/zh/latest/plugins/opa.md
@@ -910,7 +910,10 @@ role_permissions := {
 
 # Get JWT authorization token
 bearer_token := t if {
-  t := input.request.headers.authorization
+  parts := split(input.request.headers.authorization, " ")
+  count(parts) == 2
+  lower(parts[0]) == "bearer"
+  t := parts[1]
 }
 
 # Decode the token to get role and permission
diff --git a/docs/zh/latest/plugins/prometheus.md 
b/docs/zh/latest/plugins/prometheus.md
index 48cd6a4aba..f7daef7eed 100644
--- a/docs/zh/latest/plugins/prometheus.md
+++ b/docs/zh/latest/plugins/prometheus.md
@@ -573,7 +573,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes"; -X PUT \
       "checks": {
         "active": {
           "timeout": 5,
-          "http_path": "/status",
+          "http_path": "/status/200",
           "healthy": {
             "interval": 2,
             "successes": 1
@@ -610,11 +610,11 @@ curl "http://127.0.0.1:9091/apisix/prometheus/metrics";
 ```text
 # HELP apisix_upstream_status 上游健康检查的状态
 # TYPE apisix_upstream_status gauge
-apisix_upstream_status{name="/apisix/routes/1",ip="54.237.103.220",port="80"} 1
-apisix_upstream_status{name="/apisix/routes/1",ip="127.0.0.1",port="20001"} 0
+apisix_upstream_status{name="/apisix/routes/prometheus-route",ip="54.237.103.220",port="80"}
 1
+apisix_upstream_status{name="/apisix/routes/prometheus-route",ip="127.0.0.1",port="20001"}
 0
 ```
 
-这显示上游节点 `httpbin.org:80` 是健康的,而上游节点 `127.0.0.1:20001` 是不健康的。
+假设端口 `20001` 上没有服务监听,此输出显示上游节点 `httpbin.org:80` 是健康的,而上游节点 `127.0.0.1:20001` 
是不健康的。HTTPBin 在 `/status/200` 返回 `200`。实际解析的 IP 地址可能不同,健康检查也需要时间来更新节点状态。
 
 ### 为指标添加额外标签
 

Reply via email to