moonming opened a new issue, #3414:
URL: https://github.com/apache/apisix-dashboard/issues/3414

   ### Issue description
   
   Opening a route (or service / stream route) whose **inline upstream has 
health checks configured**, clicking **Edit**, and clicking **Save without 
changing anything** silently deletes `upstream.checks` from the resource. The 
UI shows a green "Edit Route Successfully" toast; the health checks are gone.
   
   Reproduced on `master` (`9979b31`) against a real APISIX instance.
   
   ### Root cause
   
   The detail pages' refetch-reset path uses the wrong producer for the 
health-check UI flags:
   
   - The health-check section is driven by a form-root-level virtual flag: 
`FormSectionChecks.tsx` registers `__checksEnabled` **unprefixed** and reads it 
via `useWatch({ name: '__checksEnabled' })`.
   - `src/routes/routes/detail.$id.tsx` resets the form with 
`produceToNestedUpstreamForm(routeData.value)`, but that producer 
(`src/components/form-slice/FormPartUpstream/util.ts:34-49`) writes the flags 
**nested** under `upstream.__checksEnabled` (it only sets root-level flags `if 
(d.checks)`, which routes/services never have at the top level).
   - After the reset, the root-level watch reads `undefined` → the checks 
section renders as "disabled" → its inputs unmount → with `shouldUnregister: 
true` on the form, `upstream.checks` is omitted from the PUT body → the Admin 
API PUT replaces the resource without checks.
   
   Affected pages (same reset pattern): `routes/detail.$id.tsx`, 
`services/detail.$id/index.tsx`, `stream_routes/detail.$id.tsx`.
   
   ### How to Reproduce
   
   1. Create a route with an inline upstream carrying active health checks via 
the Admin API:
      ```bash
      curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/checks-repro \
        -H "X-API-KEY: $KEY" -d '{
          "uri": "/checks-repro",
          "upstream": {
            "type": "roundrobin",
            "nodes": {"127.0.0.1:8000": 1},
            "checks": {"active": {"type": "http", "http_path": "/health",
              "healthy": {"interval": 2, "successes": 2},
              "unhealthy": {"interval": 2, "http_failures": 3}}}
          }}'
      ```
   2. Open the route's detail page in the dashboard → **Edit** → **Save** 
(change nothing).
   3. `GET /apisix/admin/routes/checks-repro` → `upstream.checks` is gone.
   
   ### Expected behavior
   
   A save that changes nothing must be a no-op: the resource read back after 
save is identical to what was there before (health checks included).
   
   ### Why this is severe
   
   This is silent data loss on the most routine action in the product — a user 
editing a route's description destroys their health-check configuration with 
zero feedback. It is also invisible to the current e2e suite: no round-trip 
test asserts field preservation across a no-op edit-save.
   
   ### Suggested fix
   
   Make `produceToNestedUpstreamForm` also derive the root-level flags from the 
nested upstream:
   
   ```ts
   if (d.upstream && typeof d.upstream === 'object' && 
!Array.isArray(d.upstream)) {
     d.upstream = produceToUpstreamForm(d.upstream, d.upstream);
     d.__checksEnabled = !!(d.upstream as Upstream).checks && 
isNotEmpty((d.upstream as Upstream).checks);
     d.__checksPassiveEnabled = !!(d.upstream as Upstream).checks?.passive && 
isNotEmpty(...);
   }
   ```
   
   plus a regression e2e: `route detail preserves upstream.checks after no-op 
edit-save`. I'm preparing a PR.
   
   ### Environment
   
   - apisix-dashboard: master (`9979b31`), UI served by `pnpm dev` against 
APISIX master via the standard `/apisix/admin` proxy
   


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