Skip to content

fix(proxy-mirror): keep the original method path when mirroring gRPC requests#13499

Merged
nic-6443 merged 1 commit into
apache:masterfrom
nic-6443:fix/proxy-mirror-grpc-path
Jun 10, 2026
Merged

fix(proxy-mirror): keep the original method path when mirroring gRPC requests#13499
nic-6443 merged 1 commit into
apache:masterfrom
nic-6443:fix/proxy-mirror-grpc-path

Conversation

@nic-6443

Copy link
Copy Markdown
Member

Description

Fixes #13498

When proxy-mirror mirrors to a grpc:// host, the mirrored request was sent with :path = /proxy_mirror_grpc (the internal mirror location name) instead of the real gRPC method path, so the mirror backend rejects every call with UNIMPLEMENTED. The cause is that grpc_pass cannot carry a URI (unlike the HTTP mirror location, which uses proxy_pass $upstream_mirror_uri), so the grpc module builds :path from the mirror subrequest's own URI.

The fix captures the request path into a new $upstream_mirror_grpc_path variable and rewrites the mirror subrequest URI with it in the proxy_mirror_grpc location before grpc_pass. The capture happens in the before_proxy phase rather than rewrite, because access phase plugins (e.g. grpc-web) may rewrite the URI after proxy-mirror's rewrite phase has run; before_proxy runs after all of them, so the mirrored :path always matches what the main upstream receives. path / path_concat_mode stay not applicable to gRPC mirroring, as already documented.

The existing grpc mirror test from #9388 only asserted Connection refused against a closed port, so it could not catch this. It is reworked to mirror into a local h2c server that records the received request, asserting the :path, content-type and body length of the mirrored request; a second case covers the combination with grpc-web. Both fail before this fix (the mirror target receives path=/proxy_mirror_grpc) and pass after.

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible

…requests

The grpc mirror location only has grpc_pass, which cannot carry a URI, so
the mirrored request was sent with :path of the mirror subrequest URI
/proxy_mirror_grpc. The gRPC mirror backend rejects such calls with
UNIMPLEMENTED, making gRPC mirroring unusable.

Capture the request path into the new $upstream_mirror_grpc_path variable
in the before_proxy phase, which runs after access phase plugins (e.g.
grpc-web) have rewritten the URI, and rewrite the mirror subrequest URI
with it before grpc_pass.

Fixes apache#13498
Copilot AI review requested due to automatic review settings June 10, 2026 03:54
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. bug Something isn't working labels Jun 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes gRPC mirroring in the proxy-mirror plugin so mirrored gRPC subrequests preserve the effective method path (including URI rewrites performed by access-phase plugins like grpc-web), instead of incorrectly using the internal mirror location URI (/proxy_mirror_grpc).

Changes:

  • Capture the final request URI in before_proxy into a new Nginx var ($upstream_mirror_grpc_path) for gRPC mirroring.
  • Rewrite the internal /proxy_mirror_grpc subrequest URI to $upstream_mirror_grpc_path before grpc_pass, so the mirrored :path matches the main upstream request.
  • Rework the gRPC mirror test to assert the mirrored request’s :path, content-type, and body length (and add a grpc-web combined case).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apisix/plugins/proxy-mirror.lua Adds before_proxy hook to capture the effective URI into $upstream_mirror_grpc_path when mirroring is enabled.
apisix/cli/ngx_tpl.lua Declares $upstream_mirror_grpc_path and rewrites the gRPC mirror subrequest URI before grpc_pass.
apisix/core/ctx.lua Registers upstream_mirror_grpc_path as a writable cached Nginx variable in ctx.var.
t/APISIX.pm Updates test Nginx config template to declare and use $upstream_mirror_grpc_path for gRPC mirroring.
t/plugin/proxy-mirror3.t Replaces the old “connection refused” gRPC mirror test with an h2c mirror server that validates mirrored request properties, plus a grpc-web case.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread t/plugin/proxy-mirror3.t
Comment thread t/plugin/proxy-mirror3.t
@nic-6443
nic-6443 merged commit 75bb631 into apache:master Jun 10, 2026
28 of 29 checks passed
@nic-6443
nic-6443 deleted the fix/proxy-mirror-grpc-path branch June 10, 2026 06:31
wistefan pushed a commit to wistefan/apisix that referenced this pull request Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: proxy-mirror sends mirrored gRPC requests with :path /proxy_mirror_grpc instead of the original method path

5 participants