1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! An example to show how to listen on a Unix (domain) socket,
//! for incoming connections. This can be useful for "local" interactions
//! with your public service or for a local-first service.
//!
//! # Run the example
//!
//! ```sh
//! cargo run --example unix_socket_http --features=http-full,unix
//! ```
//!
//! # Expected output
//!
//! The server will start and listen on `/tmp/rama_example_unix_http.socket`.
//! You can use `curl` to interact with the service:
//!
//! ```sh
//! curl --unix-socket /tmp/rama_example_unix_http.socket http://localhost/ping
//! ```
//!
//! You should receive `pong` back as the payload of a 200 OK response.
//! The host here is ignored and is just to make the uri valid.
#![cfg_attr(
target_family = "unix",
expect(
clippy::expect_used,
reason = "example: panic-on-error is the standard pattern for demos"
)
)]
#[cfg(target_family = "unix")]
mod unix_example {
use rama::{
Layer,
http::{
layer::error_handling::ErrorHandlerLayer, server::HttpServer, service::web::Router,
},
layer::ArcLayer,
rt::Executor,
telemetry::tracing::{
self,
level_filters::LevelFilter,
subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt},
},
unix::server::UnixListener,
};
pub(super) async fn run() {
tracing::subscriber::registry()
.with(fmt::layer())
.with(
EnvFilter::builder()
.with_default_directive(LevelFilter::DEBUG.into())
.from_env_lossy(),
)
.init();
let graceful = rama::graceful::Shutdown::default();
let exec = Executor::graceful(graceful.guard());
const PATH: &str = "/tmp/rama_example_unix_http.socket";
let listener = UnixListener::bind_path(PATH, exec.clone())
.await
.expect("bind Unix socket");
graceful.spawn_task(async move {
tracing::info!(
file.path = %PATH,
"ready to unix-serve",
);
listener
.serve(
HttpServer::new_http1(exec).service(
(ArcLayer::new(), ErrorHandlerLayer::new())
.into_layer(Router::new().with_get("/ping", "pong")),
),
)
.await;
});
let duration = graceful.shutdown().await;
tracing::info!(
shutdown.duration_ms = %duration.as_millis(),
"bye!",
);
}
}
#[cfg(target_family = "unix")]
use unix_example::run;
#[cfg(not(target_family = "unix"))]
async fn run() {
eprintln!("unix_socket example is a unix-only example, bye now!");
}
#[tokio::main]
async fn main() {
run().await
}