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}