nic-6443 opened a new issue, #13498:
URL: https://github.com/apache/apisix/issues/13498

   ### Current Behavior
   
   When `proxy-mirror` is configured with a `grpc://` host, the mirrored 
request arrives at the mirror target with `:path = /proxy_mirror_grpc` (the 
name of the internal nginx location) instead of the real gRPC method path. A 
gRPC server receiving such a call just rejects it with `UNIMPLEMENTED`, so gRPC 
mirroring is effectively unusable — the mirror backend never sees a valid call.
   
   The root cause is in the generated nginx config: the HTTP mirror location 
forwards with `proxy_pass $upstream_mirror_uri` which carries the full URI, but 
the gRPC mirror location only has `grpc_pass $upstream_mirror_host`. 
`grpc_pass` cannot carry a URI, so the grpc module builds `:path` from the 
subrequest's own URI, which is the mirror location name `/proxy_mirror_grpc`.
   
   The existing test case in `t/plugin/proxy-mirror3.t` (added in #9388) only 
asserts `Connection refused` against a closed port, so it never verified what 
the mirrored gRPC request actually contains and this went unnoticed.
   
   There is also a phase-timing aspect: plugins like `grpc-web` rewrite the 
request URI in their access phase, while `proxy-mirror` captures the URI in its 
rewrite phase, so the mirror path must be taken after all access phase plugins 
have run.
   
   ### Expected Behavior
   
   The mirrored gRPC request keeps the same method path as the upstream 
request, including rewrites done by access phase plugins (e.g. `grpc-web`).
   
   ### Error Logs
   
   No error on the APISIX side. The mirror target receives `POST 
/proxy_mirror_grpc HTTP/2.0` (verified with an h2c server logging the incoming 
`:path`).
   
   ### Steps to Reproduce
   
   1. Create a route with a `grpc` scheme upstream and `proxy-mirror` pointing 
to a `grpc://` mirror host:
   
   ```yaml
   routes:
     - uris:
         - /helloworld.Greeter/SayHello
       plugins:
         proxy-mirror:
           host: grpc://127.0.0.1:19797
       upstream:
         scheme: grpc
         nodes:
           "127.0.0.1:10051": 1
         type: roundrobin
   ```
   
   2. Run any h2c server on 19797 that logs the request path (the mirror 
target).
   3. Send a request: `grpcurl -plaintext -d '{"name":"apisix"}' 127.0.0.1:1984 
helloworld.Greeter.SayHello`
   4. The main upstream receives `POST /helloworld.Greeter/SayHello HTTP/2.0`, 
while the mirror target receives `POST /proxy_mirror_grpc HTTP/2.0`.
   
   ### Environment
   
   - APISIX version: reproduced on master and 3.14.1
   - Operating system: Ubuntu 22.04
   - OpenResty / Nginx version: apisix-runtime (openresty 1.29)
   
   I have a fix ready: capture the mirror path into a new 
`$upstream_mirror_grpc_path` variable in the `before_proxy` phase (which runs 
after all access phase plugins have rewritten the URI), and rewrite the mirror 
subrequest URI with it in the `proxy_mirror_grpc` location before `grpc_pass`. 
Will submit a PR shortly.
   


-- 
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