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}