powhttp_sdk/runtime/
mod.rs1use std::future::Future;
2use std::sync::Arc;
3use crate::error::Error;
4use crate::runtime::handle::ExtensionHandle;
5use crate::runtime::state::{ExtensionState, ShutdownHandle};
6
7pub(crate) mod handlers;
8pub(crate) mod handle;
9pub(crate) mod state;
10
11pub async fn run<F, Fut>(init: F) -> Result<(), Error>
27where
28 F: FnOnce(ExtensionHandle) -> Fut + Send + 'static,
29 Fut: Future<Output = Result<(), Error>> + Send + 'static,
30{
31 let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel();
32 let state = Arc::new(ExtensionState::new(ShutdownHandle::new(shutdown_tx)));
33
34 let app = tokio_jrpc::App::new(tokio::io::stdin(), tokio::io::stdout(), state.clone())
35 .method("context_menu/call_item_handler_single", handlers::context_menu::call_item_handler_single)
36 .method("context_menu/call_item_handler_multi", handlers::context_menu::call_item_handler_multi)
37 .method("overview/get_field_value", handlers::overview::get_field_value)
38 .method("inspector/is_request_tab_visible", handlers::inspector::is_request_tab_visible)
39 .method("inspector/is_response_tab_visible", handlers::inspector::is_response_tab_visible)
40 .method("inspector/get_request_tab_content", handlers::inspector::get_request_tab_content)
41 .method("inspector/get_response_tab_content", handlers::inspector::get_response_tab_content)
42 .method("proxy_server/call_connect_handler", handlers::proxy_server::call_connect_handler);
43
44 let client = app.client_handle();
45 let handle = ExtensionHandle::new(client, state);
46
47 let init_task = tokio::spawn(async move {
48 let stop = handle.clone();
49 match init(handle).await {
50 Ok(()) => Ok(()),
51 Err(err) => {
52 eprintln!("extension init error: {err}");
53 stop.shutdown().await;
54 Err(err)
55 }
56 }
57 });
58
59 enum AppResult {
60 Ran(Result<(), tokio_jrpc::RuntimeError>),
61 Shutdown,
62 }
63
64 let run_fut = app.run();
65 tokio::pin!(run_fut);
66
67 let app_result = tokio::select! {
68 r = &mut run_fut => AppResult::Ran(r),
69 _ = shutdown_rx => AppResult::Shutdown,
70 };
71
72 init_task.await.map_err(Error::new)??;
73
74 match app_result {
75 AppResult::Ran(r) => r.map_err(Error::from),
76 AppResult::Shutdown => Ok(()),
77 }
78}