Skip to main content

rs_teststand_websocket/server/
options.rs

1//! What a host decides before it binds.
2
3/// How a host serves: what it hands a browser, and who it will talk to.
4///
5/// Built by chaining, and every field has a default that works, so a host only
6/// names what it cares about.
7///
8/// ```
9/// use rs_teststand_websocket::Options;
10///
11/// let options = Options::default()
12///     .page(include_str!("../../examples/panel.html"))
13///     .allow_origin("http://192.0.2.10:50751");
14/// ```
15#[derive(Debug, Default, Clone)]
16pub struct Options {
17    /// Served to a browser asking for the root, when set.
18    pub(super) page: Option<String>,
19    /// Origins allowed to open a socket, beyond the two rules in
20    /// [`super::origin::is_allowed`].
21    pub(super) allowed_origins: Vec<String>,
22}
23
24impl Options {
25    /// Serves `html` to a browser that asks for the root.
26    ///
27    /// One address for the panel and the socket, so opening the host's address
28    /// is the whole setup. It also gives them the same origin, which is what
29    /// lets the host trust its own panel without being told an address it picks
30    /// at bind time. A page loaded from disk instead has an origin of `null`
31    /// and gets no such trust.
32    #[must_use]
33    pub fn page(mut self, html: impl Into<String>) -> Self {
34        self.page = Some(html.into());
35        self
36    }
37
38    /// Allows `origin` to open a socket.
39    ///
40    /// Written the way a browser sends it, scheme and authority with no
41    /// trailing slash, such as `http://192.0.2.10:50751`. Matching is exact.
42    ///
43    /// Needed only for a panel the host does not serve itself, since a page it
44    /// serves already shares its origin and a native client sends no origin at
45    /// all. Call it more than once to allow several.
46    #[must_use]
47    pub fn allow_origin(mut self, origin: impl Into<String>) -> Self {
48        self.allowed_origins.push(origin.into());
49        self
50    }
51}