greentic_runner_host/runner/
mod.rs1pub 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}