fix(admin): add /rpc proxy route so the admin UI can reach the server #99
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_books!99
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "development_fix_admin_rpc_proxy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The admin dashboard pages were silently 404ing on every data load because
hero_books_adminnever registered a/rpcroute. Every template uses a JavaScriptrpc()helper that POSTs toBASE_PATH + "/rpc". This PR adds the missing proxy, mirroring the pattern already inhero_books_ui.Related Issue
Closes #98
Changes
crates/hero_books_admin/src/proxy.rs(new) — copied verbatim fromcrates/hero_books_ui/src/proxy.rs, with admin-duplicated items (BasePath,HeroRequestContext,base_path_middleware) and unusedimg_proxy/pdf_proxyremoved.AppState,proxy_request, andapi_proxyare byte-identical to the UI version — same 502-on-upstream-failure behaviour, sameContent-Type/Authorizationrequest-header allowlist.crates/hero_books_admin/src/main.rs— resolves the upstream socket (HERO_BOOKS_SOCKETenv override, falling back tohero_books_lib::default_server_socket_path()), constructsproxy_state = AppState { server_socket: Arc::new(...) }, and merges a small sub-routerRouter::new().route("/rpc", any(api_proxy)).with_state(proxy_state)into the main admin router. Admin's ownRouter<()>state is untouched.crates/hero_books_admin/tests/rpc_proxy.rs(new) — integration test.round_trip_okspawns a stub Unix-socket HTTP listener and asserts a JSON-RPC body round-trips verbatim.upstream_unreachable_returns_502asserts HTTP 502 when the upstream socket is missing.crates/hero_books_admin/Cargo.toml— added[dev-dependencies]withtower = { version = "0.5", features = ["util"] }so the test can calltower::ServiceExt::oneshot.macOS note
The integration test roots its per-run tempdir under
/tmprather thanstd::env::temp_dir(). macOS resolves the latter to/var/folders/..., which exceeds the 104-byteSUN_LENlimit for Unix sockets once a subdirectory and filename are appended. A short doc comment in the test explains the constraint.Test Results
cargo build -p hero_books_admin— ok.cargo clippy -p hero_books_admin -- -D warningsand--tests -- -D warnings— clean.hero_books_admintests: 2/2 passed (round_trip_ok,upstream_unreachable_returns_502).hero_books_serverlibrary regression gate: 16/16 passed.cargo fmt --check -p hero_books_admin— clean.Out of scope
hero_books_uiandhero_books_adminto theopenrpc_proxy!macro (current manualproxy.rsmatches the sibling crate; macro migration is a larger refactor).architecture.md, addingdocs/manual/docusaurus.md) — still pending as docs-only follow-ups.Every page in hero_books_admin used a JavaScript rpc() helper that POSTed to BASE_PATH + "/rpc", but the admin router never registered /rpc — so Libraries, Collections, Import, Export, and Health all 404ed on data load in the browser. Classic hero_ui_openrpc_proxy gap. The fix mirrors the pattern already in hero_books_ui: - new module crates/hero_books_admin/src/proxy.rs, copied from the UI's proxy.rs with admin-duplicated items (BasePath, HeroRequestContext, base_path_middleware) and unused img_proxy / pdf_proxy handlers removed. AppState, proxy_request, and api_proxy are byte-identical to the UI, including the 502-on-upstream-failure behaviour and the Content-Type / Authorization request-header allowlist. - crates/hero_books_admin/src/main.rs resolves the upstream socket (HERO_BOOKS_SOCKET override → hero_books_lib::default_server_socket_path() fallback) and merges a small sub-router Router::new().route("/rpc", any(api_proxy)).with_state(proxy_state) into the main admin router so admin's own Router<()> state is untouched. - new integration test crates/hero_books_admin/tests/rpc_proxy.rs: round_trip_ok spawns a stub Unix-socket HTTP server and asserts a JSON-RPC body round-trips verbatim; upstream_unreachable_returns_502 asserts HTTP 502 when the upstream socket is missing. - dev-dep added: tower = { version = "0.5", features = ["util"] } so the test can call tower::ServiceExt::oneshot. The test roots its per-run tempdir under /tmp rather than std::env::temp_dir() — on macOS the latter resolves to /var/folders/... which exceeds the 104-byte SUN_LEN limit for Unix sockets once a subdirectory and filename are appended. A short doc comment in the test explains the constraint. Build, clippy (-D warnings including --tests), and fmt are clean. Admin tests 2/2 pass; hero_books_server regression gate 16/16 pass. #98