dhivakar020 opened a new issue, #14129:
URL: https://github.com/apache/apisix/issues/14129

   ### Current Behavior
   
   When a route uses `proxy-rewrite` to change the path and `ai-proxy` (or 
`ai-proxy-multi`) handles the request in passthrough mode, the LLM upstream 
receives the **original client path**. The path rewrite is silently ignored, 
while header rewrites from the same `proxy-rewrite` do apply.
   
   Passthrough is used when the body is not OpenAI chat/embeddings/responses, 
Anthropic or Bedrock, and `override.endpoint` has no path of its own. A common 
setup that hits this: exposing an LLM service under a prefix such as `/llm/*` 
and stripping it with `proxy-rewrite`, as the `ai-proxy` docs suggest combining 
the two plugins.
   
   Cause: the passthrough branch in `apisix/plugins/ai-proxy/base.lua` sets 
`target_path = ctx.var.uri`.
   
   Underlying this is a known gap worth flagging: after `proxy-rewrite` calls 
`ngx.req.set_uri`, `ngx.var.uri` holds the rewritten path but `ctx.var.uri` 
still returns the original one. `ctx.var` caches variables on first read, the 
router reads `uri` in `apisix/init.lua` before any plugin runs, and `uri` is 
not in `no_cacheable_var_names` (`apisix/core/ctx.lua`). `proxy-mirror` already 
works around it (`-- read the var directly as ctx.var.uri may be cached before 
the rewrite`). Other readers of `ctx.var.uri` after a rewrite (for example 
`oas-validator`, `_meta.filter` expressions) see the original path too. This 
report is only about the `ai-proxy` case, where it changes where the request is 
sent; I'm mentioning the general behaviour in case maintainers prefer to handle 
it at the core level instead.
   
   ### Expected Behavior
   
   Passthrough sends the same path a plain route would send upstream, i.e. the 
path produced by `proxy-rewrite` (`$upstream_uri`). In the example below: 
`/anything/rewritten/x`.
   
   ### Error Logs
   
   No error is logged. httpbin echoes the URL it received:
   
   ```
   "url": "https://httpbin.org/anything/original/x";
   ```
   
   Expected `https://httpbin.org/anything/rewritten/x`.
   
   ### Steps to Reproduce
   
   1. Run APISIX (master) with etcd.
   2. Create a route with `proxy-rewrite` and `ai-proxy` (endpoint without a 
path):
   
   ```bash
   curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $KEY" 
-d '{
     "uri": "/anything/original/*",
     "plugins": {
       "proxy-rewrite": { "regex_uri": ["^/anything/original/(.*)", 
"/anything/rewritten/$1"] },
       "ai-proxy": {
         "provider": "openai-compatible",
         "auth": { "header": { "Authorization": "Bearer dummy" } },
         "override": { "endpoint": "https://httpbin.org"; }
       }
     }
   }'
   ```
   
   3. Send a request whose body is not a chat/embeddings payload, so 
passthrough is used:
   
   ```bash
   curl -X POST http://127.0.0.1:9080/anything/original/x \
     -H "Content-Type: application/json" -d '{"foo":"bar"}'
   ```
   
   4. The response shows `"url": "https://httpbin.org/anything/original/x"`.
   
   I have a fix with tests ready: in passthrough, use the path part of 
`$upstream_uri` when it is set (the path a plain `proxy_pass` uses) and fall 
back to `ctx.var.uri` otherwise; about 20 lines in `ai-proxy/base.lua` plus a 
test in `t/plugin/ai-proxy-passthrough.t`. Happy to open the PR if this 
direction looks right.
   
   ### Environment
   
   - APISIX version (run `apisix version`): master (`53009939`), 3.19.0
   - Operating system (run `uname -a`): Linux 6.18.54.1-microsoft-standard-WSL2 
x86_64 (Ubuntu 24.04)
   - OpenResty / Nginx version (run `openresty -V` or `nginx -V`): 
openresty/1.31.1.1 (apisix-runtime 1.4.1)
   - etcd version, if relevant (run `curl 
http://127.0.0.1:9090/v1/server_info`): 3.5.4
   - APISIX Dashboard version, if relevant: N/A
   - Plugin runner version, for issues related to plugin runners: N/A
   - LuaRocks version, for installation issues (run `luarocks --version`): N/A


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to