Skip to main content

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