allora_runtime/spec/
http_inbound_adapter_spec.rs

1//! HttpInboundAdapterSpec: specification for a single HTTP inbound adapter binding an HTTP endpoint
2//! to messaging channels.
3//!
4//! # Purpose
5//! Represents an HTTP server endpoint definition that publishes inbound requests as messages onto a
6//! `request_channel` and optionally consumes replies from a `reply_channel` to form synchronous HTTP responses.
7//!
8//! # Field Semantics
9//! * `id` (optional): Explicit adapter identifier for reference / diagnostics; may be auto-generated
10//!   by a future collection builder (`http-inbound-adapter:auto.N`).
11//! * `host` (required, non-empty): Interface or hostname to bind (e.g. `0.0.0.0`, `127.0.0.1`).
12//! * `port` (required, 1-65535): TCP port to listen on.
13//! * `path` (required, non-empty, leading `/`): Exact path segment for the endpoint.
14//! * `methods` (required, non-empty list): Allowed HTTP methods (subset of standard verbs).
15//! * `request_channel` (required, non-empty): Channel id receiving inbound requests as messages.
16//! * `reply_channel` (optional, non-empty if present): Channel id for reply messages correlated to HTTP responses.
17//!
18//! # Construction Helpers
19//! * `new(host, port, path, methods, request_channel)` – minimal spec (no id / reply_channel).
20//! * `with_id(id, host, port, path, methods, request_channel)` – explicit id.
21//! * `with_reply(host, port, path, methods, request_channel, reply_channel)` – reply channel only.
22//! * `with_id_reply(id, host, port, path, methods, request_channel, reply_channel)` – id + reply.
23//!
24//! # Example
25//! ```rust
26//! use allora_runtime::spec::HttpInboundAdapterSpec;
27//! let spec = HttpInboundAdapterSpec::new("127.0.0.1", 8080, "/receive", vec!["POST".into()], "inbound.receive");
28//! assert_eq!(spec.host(), "127.0.0.1");
29//! assert_eq!(spec.port(), 8080);
30//! assert_eq!(spec.path(), "/receive");
31//! assert_eq!(spec.methods(), &["POST"]);
32//! assert_eq!(spec.request_channel(), "inbound.receive");
33//! assert!(spec.reply_channel().is_none());
34//! ```
35
36#[derive(Debug, Clone)]
37pub struct HttpInboundAdapterSpec {
38    id: Option<String>,
39    host: String,
40    port: u16,
41    path: String,
42    methods: Vec<String>,
43    request_channel: String,
44    reply_channel: Option<String>,
45}
46
47impl HttpInboundAdapterSpec {
48    pub fn new<H: Into<String>, P: Into<String>, RC: Into<String>>(
49        host: H,
50        port: u16,
51        path: P,
52        methods: Vec<String>,
53        request_channel: RC,
54    ) -> Self {
55        Self {
56            id: None,
57            host: host.into(),
58            port,
59            path: path.into(),
60            methods,
61            request_channel: request_channel.into(),
62            reply_channel: None,
63        }
64    }
65    pub fn with_id<ID: Into<String>, H: Into<String>, P: Into<String>, RC: Into<String>>(
66        id: ID,
67        host: H,
68        port: u16,
69        path: P,
70        methods: Vec<String>,
71        request_channel: RC,
72    ) -> Self {
73        Self {
74            id: Some(id.into()),
75            host: host.into(),
76            port,
77            path: path.into(),
78            methods,
79            request_channel: request_channel.into(),
80            reply_channel: None,
81        }
82    }
83    pub fn with_reply<H: Into<String>, P: Into<String>, RC: Into<String>, R: Into<String>>(
84        host: H,
85        port: u16,
86        path: P,
87        methods: Vec<String>,
88        request_channel: RC,
89        reply_channel: R,
90    ) -> Self {
91        Self {
92            id: None,
93            host: host.into(),
94            port,
95            path: path.into(),
96            methods,
97            request_channel: request_channel.into(),
98            reply_channel: Some(reply_channel.into()),
99        }
100    }
101    pub fn with_id_reply<
102        ID: Into<String>,
103        H: Into<String>,
104        P: Into<String>,
105        RC: Into<String>,
106        R: Into<String>,
107    >(
108        id: ID,
109        host: H,
110        port: u16,
111        path: P,
112        methods: Vec<String>,
113        request_channel: RC,
114        reply_channel: R,
115    ) -> Self {
116        Self {
117            id: Some(id.into()),
118            host: host.into(),
119            port,
120            path: path.into(),
121            methods,
122            request_channel: request_channel.into(),
123            reply_channel: Some(reply_channel.into()),
124        }
125    }
126    pub fn id(&self) -> Option<&str> {
127        self.id.as_deref()
128    }
129    pub fn host(&self) -> &str {
130        &self.host
131    }
132    pub fn port(&self) -> u16 {
133        self.port
134    }
135    pub fn path(&self) -> &str {
136        &self.path
137    }
138    pub fn methods(&self) -> &[String] {
139        &self.methods
140    }
141    pub fn request_channel(&self) -> &str {
142        &self.request_channel
143    }
144    pub fn reply_channel(&self) -> Option<&str> {
145        self.reply_channel.as_deref()
146    }
147    pub fn set_id(&mut self, id: String) {
148        self.id = Some(id);
149    }
150}