pub struct ServerFuture(/* private fields */);Expand description
Opaque future returned by Server::serve, Server::serve_with_graceful_shutdown,
and Server::serve_from_listener.
A ServerFuture can be used in two ways:
.await— drives the server inline in the current task..background()— spawns the server on a new Tokio task and returns atokio::task::JoinHandle<()>immediately.
Implementations§
Source§impl ServerFuture
impl ServerFuture
Sourcepub fn background(self) -> JoinHandle<()>
pub fn background(self) -> JoinHandle<()>
Spawns the server on a new Tokio background task and returns a JoinHandle<()>.
§Panics
Panics if called outside a Tokio runtime.
Examples found in repository?
examples/socket_macros.rs (line 144)
80async fn main() -> Result<(), Box<dyn std::error::Error>> {
81 let store: Arc<Mutex<Vec<Item>>> = Arc::new(Mutex::new(vec![]));
82 let mut server = Server::default();
83
84 // ── Register routes via #[mechanism] ────────────────────────────────────
85 //
86 // Each attribute expands to:
87 // server.mechanism(ServerMechanism::METHOD(path)[.modifier()].onconnect(fn));
88
89 // Plain GET — no body, no state.
90 #[mechanism(server, GET, "/health")]
91 async fn health_handler() {
92 reply!(json => Health { ok: true })
93 }
94
95 // POST + JSON body — returns the created item.
96 #[mechanism(server, POST, "/items", json)]
97 async fn create_item(body: NewItem) {
98 reply!(json => Item { id: 1, name: body.name }, status => Status::Created)
99 }
100
101 // GET + query params — echoes back the search prefix.
102 // (Filtered search requires access to the store; see /items/store below.)
103 #[mechanism(server, GET, "/items/search", state(store.clone()), query)]
104 async fn search_items(state: Arc<Mutex<Vec<Item>>>, f: Filter) {
105 let items = state.lock().unwrap();
106 let matches: Vec<Item> = items
107 .iter()
108 .filter(|i| i.name.starts_with(&f.prefix))
109 .cloned()
110 .collect();
111 reply!(json => SearchResult { matches })
112 }
113
114 // POST + shared state + JSON body — persists the item.
115 #[mechanism(server, POST, "/items/store", state(store.clone()), json)]
116 async fn store_item(state: Arc<Mutex<Vec<Item>>>, body: NewItem) {
117 let mut s = state.lock().unwrap();
118 let id = s.len() as u32 + 1;
119 let item = Item { id, name: body.name };
120 s.push(item.clone());
121 reply!(json => item, status => Status::Created)
122 }
123
124 // POST + AEAD-encrypted body (ChaCha20-Poly1305 via SerializationKey).
125 // The body is decrypted before the handler is called; the response is
126 // sealed so the client's `.send::<Item>()` can open it automatically.
127 #[mechanism(server, POST, "/items/secure", encrypted(SerializationKey::Default))]
128 async fn secure_create(body: NewItem) {
129 let item = Item { id: 99, name: body.name };
130 reply!(sealed => item, key => SerializationKey::Default)
131 }
132
133 // ── Start the server in the background via .background() ────────────────
134 //
135 // Previously this required manually wrapping the `.await` call inside
136 // `tokio::spawn(async move { server.serve_*(…).await; })`.
137 // `.background()` is the idiomatic shorthand for exactly that pattern.
138 let (tx, rx) = tokio::sync::oneshot::channel::<()>();
139 let server_handle = server
140 .serve_with_graceful_shutdown(
141 ([127, 0, 0, 1], PORT),
142 async { rx.await.ok(); },
143 )
144 .background(); // ← non-blocking spawn
145
146 // Give the server a moment to bind before firing requests.
147 tokio::time::sleep(Duration::from_millis(200)).await;
148 println!("Server started on port {PORT}");
149
150 // ── Issue all requests via #[request] ───────────────────────────────────
151 //
152 // Each attribute expands to an expression that sends the request and awaits
153 // the response, binding the decoded value to a local with the function name.
154
155 let client = ClientBuilder::new(Target::Localhost(PORT))
156 .timeout(Duration::from_secs(5))
157 .build_async();
158
159 // Async GET /health — plain request, no body.
160 #[request(client, GET, "/health", async)]
161 async fn health_resp() -> Health {}
162 assert!(health_resp.ok);
163 println!("GET /health → ok={}", health_resp.ok);
164
165 // Async POST /items — JSON body.
166 #[request(client, POST, "/items", json(NewItem { name: "widget".to_string() }), async)]
167 async fn created() -> Item {}
168 assert_eq!(created.name, "widget");
169 println!("POST /items → {:?}", created);
170
171 // Store a couple of items so the search route has data.
172 #[request(client, POST, "/items/store", json(NewItem { name: "gadget".to_string() }), async)]
173 async fn stored1() -> Item {}
174 println!("POST /items/store → {:?}", stored1);
175
176 #[request(client, POST, "/items/store", json(NewItem { name: "gizmo".to_string() }), async)]
177 async fn stored2() -> Item {}
178 println!("POST /items/store → {:?}", stored2);
179
180 // Async GET /items/search?prefix=ga — query params with shared state.
181 #[request(client, GET, "/items/search", query(Filter { prefix: "ga".to_string() }), async)]
182 async fn results() -> SearchResult {}
183 assert!(results.matches.iter().all(|i| i.name.starts_with("ga")));
184 println!(
185 "GET /items/search?prefix=ga → {} match(es): {:?}",
186 results.matches.len(),
187 results.matches
188 );
189
190 // Async POST /items/secure — AEAD-encrypted body.
191 #[request(client, POST, "/items/secure", encrypted(NewItem { name: "secret".to_string() }, SerializationKey::Default), async)]
192 async fn secure_item() -> Item {}
193 assert_eq!(secure_item.name, "secret");
194 println!("POST /items/secure → {:?}", secure_item);
195
196 // ── Graceful shutdown ───────────────────────────────────────────────────
197 tx.send(()).ok();
198 server_handle.await?;
199 println!("\nAll requests successful ✓");
200 Ok(())
201}Trait Implementations§
Source§impl IntoFuture for ServerFuture
impl IntoFuture for ServerFuture
Auto Trait Implementations§
impl Freeze for ServerFuture
impl !RefUnwindSafe for ServerFuture
impl Send for ServerFuture
impl !Sync for ServerFuture
impl Unpin for ServerFuture
impl UnsafeUnpin for ServerFuture
impl !UnwindSafe for ServerFuture
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more