modulink_rs/listeners/
http_listener.rs1
2
3
4
5use axum::{Router, routing::post, extract::State, Json};
6use crate::context::Context;
7use crate::listeners::BaseListenerAsync;
8use std::sync::Arc;
9use std::net::SocketAddr;
10use async_trait::async_trait;
11
12
13
14pub struct HttpListener {
17 pub handler: Arc<dyn Fn(Context) -> std::pin::Pin<Box<dyn std::future::Future<Output = Context> + Send>> + Send + Sync>,
18 pub addr: String,
19}
20
21
22
23
24#[async_trait]
25impl BaseListenerAsync for HttpListener {
26 async fn start(&self) -> std::io::Result<()> {
27 let handler = self.handler.clone();
28 let addr: SocketAddr = self.addr.parse().expect("Invalid address");
29
30 let handler_clone = handler.clone();
32 let app = Router::new()
33 .route("/run", post(
34 move |State(handler): State<Arc<dyn Fn(Context) -> std::pin::Pin<Box<dyn std::future::Future<Output = Context> + Send>> + Send + Sync>>, Json(body): Json<serde_json::Value>| {
35 let handler = handler.clone();
36 async move {
37 let map = body.as_object().cloned().unwrap_or_default();
38 let ctx = Context(map.into_iter().collect());
39 let result = handler(ctx).await;
40 let map: serde_json::Map<String, serde_json::Value> = result.0.into_iter().collect();
42 Json(serde_json::Value::Object(map))
43 }
44 }
45 ))
46 .with_state(handler_clone);
47
48 use axum::serve;
50 use tokio::net::TcpListener;
51 let listener = TcpListener::bind(addr).await.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
52 serve(listener, app.into_make_service()).await.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
53 }
54 fn name(&self) -> &'static str {
55 "http"
56 }
57}