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