AlinsRan commented on issue #2782:
URL: 
https://github.com/apache/apisix-ingress-controller/issues/2782#issuecomment-4665840885

   ### #2703 is not backward compatible
   
   Before #2703 (i.e. 2.0.x), routes carried no `server_port` var, so requests 
on any listening port matched. #2703 first shipped in 2.1.0 and, with the 
default `listener_port_match_mode: auto`, injects a `server_port` var into 
every route that matches multiple listener ports — with **no config change** on 
the user's side. The "current behavior maintained" claim only refers to 
compatibility with the unreleased PR, not with the last release 2.0.x. For 
upgrading users this is a silent breaking change.
   
   **Why it gets injected here (even without `sectionName`/`port`):** the 
default mode `auto` injects when a route explicitly targets a listener **or** 
when it matches multiple listener ports:
   
   ```go
   case config.ListenerPortMatchModeAuto:
       return explicit || len(ports) > 1
   ```
   
   The HTTPRoute in this report has no `sectionName`/`port` and hostname 
`git.example.com`, which matches **both** listeners — `http` (80, no hostname → 
matches any) and `https` (443, `*.example.com` → matches `git.example.com`). So 
`listenerPorts = {80, 443}`, `len(ports) > 1` is true, and `server_port in 
["80","443"]` is injected.
   
   **Why it then 404s:** the injected values `80`/`443` are the Gateway's 
**logical** listener ports, but the nginx/APISIX `$server_port` variable 
reflects the port **APISIX actually listens on**. In the standard Helm deploy 
APISIX listens internally on `9080`/`9443` (the Service/LoadBalancer maps 
external 80/443 → 9080/9443), so `$server_port` is `9080`/`9443` at request 
time and never matches `in ["80","443"]` → 404.
   
   (The #2703 e2e tests don't catch this because they set APISIX `node_listen` 
to the same ports as the Gateway listeners — `9080`/`9081` — so listener port 
== actual listening port there, a condition that does not hold in typical 
deployments.)
   
   ### Temporary fix for affected users
   
   Set the controller config to disable the injection:
   
   ```yaml
   listener_port_match_mode: off
   ```
   
   This restores the 2.0.x matching behavior without any other change.
   
   ### How this should be handled going forward
   
   1. **The default should be `off`.** `server_port` injection must be opt-in:
      - **Semantics:** a route attaching without `sectionName`/`port` means 
"attach to all compatible listeners" and should match on all of them. The 
`auto` heuristic (`len(ports) > 1`) turns the *normal* multi-listener 
attachment into port filtering even though the user never expressed any 
port-routing intent. The case that legitimately wants listener isolation is 
explicit `sectionName`/`port` targeting, which is opt-in by nature.
      - **Compatibility:** `auto` as default silently changes matching for 
every multi-listener deployment on upgrade.
      - This should ship as a 2.1.x patch so existing users recover without 
touching their manifests.
   
   2. **The mechanism itself needs a redesign before any inject-by-default mode 
is safe.** Matching `$server_port` against the Gateway's logical listener port 
is incorrect whenever port remapping is in play (Service/LoadBalancer, custom 
`node_listen`, etc.) — which is the common case. Toggling *when* to inject does 
not fix *what* is injected. A correct implementation has to map the Gateway 
listener port to APISIX's actual listening port (or drop `server_port` for 
listener disambiguation). This deserves a separate design discussion and should 
not block the default change in (1).
   


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