wgzhao opened a new pull request, #12775: URL: https://github.com/apache/seatunnel/pull/12775
### Purpose of this pull request Fix the Web UI 404 that appears when a client sends the route fragment percent-encoded in the request path instead of keeping it on the client. **Reported symptom** (Zeta 3.0.0, Safari): the Web UI opens fine at `http://host:8080/#/overview`, but re-requesting that page answers with the bare Jetty error page: ``` HTTP ERROR 404 Not Found URI: /%23/overview STATUS: 404 SERVLET: default ``` **Root cause.** The Web UI is a single page application and keeps its route in the URL fragment, so the browser normally keeps `#/overview` on the client and only requests `/`. Some clients escape the whole URL and send the fragment as part of the path instead: Safari does that when it re-requests a hash route - the address bar keeps showing `#/overview` while the request on the wire is `GET /%23/overview`. That path matches no static resource, so `DefaultServlet` answered 404. Chrome and curl keep the fragment client side, which is why the problem only shows up in some browsers. **Change.** `WebUiFragmentRedirectFilter` maps such a request back to the URL the client meant to open by moving the encoded fragment behind a real `#` and answering `302`: | Request | Response | | --- | --- | | `GET /%23/overview` | `302 Location: /#/overview` | | `GET /%23/jobs/1001?tab=metrics` | `302 Location: /#/jobs/1001?tab=metrics` | | `GET /seatunnel/%23/overview` (with `context-path`) | `302 Location: /seatunnel/#/overview` | Deliberately narrow, so nothing else changes: * only `GET` and `HEAD`; * only when the context-relative path *starts* with `/%23` - there is no catch-all, unknown paths still answer 404; * the filter is registered after the basic auth filter, so `enable-basic-auth` still answers 401 before any redirect; * REST paths and unencoded fragments never match (an unencoded fragment never reaches the server at all). A freshly served page is also a compatibility fix rather than a new feature: it makes such URLs work instead of showing a raw error page. Docs: `docs/en/engines/zeta/web-ui.md` and `docs/zh/engines/zeta/web-ui.md` describe the behavior. No config option, REST API or public API changes. ### Does this PR introduce _any_ user-facing change? Yes - a user-facing bug fix, no API or config change: * before: `GET /%23/overview` (Safari re-requesting a hash route, or a URL escaped by a chat/wiki/markdown preview) rendered the Jetty `HTTP ERROR 404 Not Found` page; * after: the same request is redirected to `/#/overview`, so the Web UI loads. Paths without a fragment keep their current meaning, for example `GET /overview` still returns cluster JSON from the REST API. ### How was this patch tested? **1. E2E integration test** (`WebUiEntryPointIT`, runs a real Zeta node with the HTTP service and the packaged Web UI, no container needed): ``` ./mvnw -pl seatunnel-e2e/seatunnel-engine-e2e/connector-seatunnel-e2e-base verify \ -DskipUT=true -DskipIT=false -Dit.test=WebUiEntryPointIT ``` Covers the reported URL, a deep link, following the redirect to the served UI entry page, the REST path, the UI root path and an unknown path. Red/green: with the filter removed from `JettyService` the test fails with `expected: <302> but was: <404>` for the three encoded-fragment cases (6 run, 3 failures), and passes 6/6 with it. **2. Unit test** for the URL mapping (`WebUiFragmentRedirectFilterTest`, 7 cases) covering the plain case, a deep link with a query string, a configured context path, an empty fragment, non-navigating methods and the negative cases (UI root, `index.html`, `/overview`, REST path with query, encoded fragment outside the context path). **3. Manual verification against a real node** (`seatunnel-engine-server` installed from this branch, HTTP service on port 18099, Web UI resources packaged): ``` $ curl -i --path-as-is 'http://127.0.0.1:18099/%23/overview' HTTP/1.1 302 Found Location: /#/overview $ curl -s -L --path-as-is -o /dev/null -w '%{http_code} %{content_type} %{url_effective}\n' \ 'http://127.0.0.1:18099/%23/overview' 200 text/html http://127.0.0.1:18099/#/overview $ curl -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:18099/' # 200, UI entry page $ curl -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:18099/overview' # 200, REST JSON $ curl -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:18099/unknown-x' # 404, unchanged ``` **4. Verified in Safari, the browser from the report**, against that node through a logging proxy so the requests are visible: Safari asked for `GET /%23/overview`, followed the `302` with a single `GET /`, rendered the Web UI at `127.0.0.1:18099/#/overview`, and a subsequent reload kept working (no redirect loop). The deployed 3.0.0 instance shows the same request shape in its 404 page (`URI: /%23/overview`). **5. `./mvnw spotless:apply`** and the `seatunnel-engine-server` REST area tests (`RestApiHttpBasicTest`, `RestApiHttpsTest`, `OptionRulesApiTest`, servlet and service tests, plus the new filter test) all pass. Note for reviewers running a full local module build: on my machine `MetricsApiTest` fails because port 8080 is already occupied by an unrelated local service, and `SavePointTest` reported a job going `FAILED` instead of `RUNNING`; neither test touches the code path changed here. -- 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]
