greentic_runner_host/runner/
mod.rs

1pub mod adapt_messaging;
2pub mod adapt_slack;
3pub mod adapt_teams;
4pub mod adapt_timer;
5pub mod adapt_webchat;
6pub mod adapt_webex;
7pub mod adapt_webhook;
8pub mod adapt_whatsapp;
9pub mod engine;
10pub mod flow_adapter;
11pub mod ingress_util;
12pub mod mocks;
13
14use std::net::SocketAddr;
15use std::sync::Arc;
16
17use anyhow::Result;
18use axum::routing::{any, get, post};
19use axum::{Router, serve};
20use tokio::net::TcpListener;
21
22use crate::http::{self, admin, auth::AdminAuth, health::HealthState};
23use crate::routing::TenantRouting;
24use crate::runtime::ActivePacks;
25use crate::watcher::PackReloadHandle;
26
27pub struct HostServer {
28    addr: SocketAddr,
29    router: Router,
30    _state: ServerState,
31}
32
33impl HostServer {
34    pub fn new(
35        port: u16,
36        active: Arc<ActivePacks>,
37        routing: TenantRouting,
38        health: Arc<HealthState>,
39        reload: Option<PackReloadHandle>,
40        admin: AdminAuth,
41    ) -> Result<Self> {
42        let addr = SocketAddr::from(([0, 0, 0, 0], port));
43        let state = ServerState {
44            active,
45            routing,
46            health,
47            reload,
48            admin,
49        };
50        let router = Router::new()
51            .route(
52                "/messaging/telegram/webhook",
53                post(adapt_messaging::telegram_webhook),
54            )
55            .route("/webchat/activities", post(adapt_webchat::activities))
56            .route("/teams/activities", post(adapt_teams::activities))
57            .route("/slack/events", post(adapt_slack::events))
58            .route("/slack/interactive", post(adapt_slack::interactive))
59            .route("/webex/webhook", post(adapt_webex::webhook))
60            .route(
61                "/whatsapp/webhook",
62                get(adapt_whatsapp::verify).post(adapt_whatsapp::webhook),
63            )
64            .route("/webhook/:flow_id", any(adapt_webhook::dispatch))
65            .route("/healthz", get(http::health::handler))
66            .route("/admin/packs/status", get(admin::status))
67            .route("/admin/packs/reload", post(admin::reload))
68            .with_state(state.clone());
69        Ok(Self {
70            addr,
71            router,
72            _state: state,
73        })
74    }
75
76    pub async fn serve(self) -> Result<()> {
77        tracing::info!(addr = %self.addr, "starting host server");
78        let listener = TcpListener::bind(self.addr).await?;
79        serve(
80            listener,
81            self.router
82                .into_make_service_with_connect_info::<SocketAddr>(),
83        )
84        .await?;
85        Ok(())
86    }
87}
88
89#[derive(Clone)]
90pub struct ServerState {
91    pub active: Arc<ActivePacks>,
92    pub routing: TenantRouting,
93    pub health: Arc<HealthState>,
94    pub reload: Option<PackReloadHandle>,
95    pub admin: AdminAuth,
96}