wgzhao opened a new pull request, #12774:
URL: https://github.com/apache/seatunnel/pull/12774

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

Reply via email to