bui_backend/lib.rs
1//! bui-backend - Brower User Interfaces (BUIs) with Tokio
2//!
3//! [![Version][version-img]][version-url] [![Status][status-img]][status-url]
4//! [![Doc][doc-img]][doc-url]
5//!
6//! [status-img]: https://github.com/astraw/bui-backend/workflows/CI/badge.svg
7//! [status-url]: https://github.com/astraw/bui-backend/actions
8//! [bui-demo]: https://github.com/astraw/bui-backend/tree/master/bui-demo
9//! [doc-img]: https://docs.rs/bui-backend/badge.svg
10//! [doc-url]: https://docs.rs/bui-backend/
11//! [version-img]: https://img.shields.io/crates/v/bui-backend.svg
12//! [version-url]: https://crates.io/crates/bui-backend
13//!
14//! This library enables an application to serve a [Browser User Interface
15//! (BUI)](https://en.wikipedia.org/wiki/Browser_user_interface). The browser
16//! becomes your GUI. The server-side API is based on futures and reactively
17//! pushes state to the browser. Assets can be served from the filesystem or
18//! bundled in the executable. The server provides an "escape hatch" to allow
19//! server-client communication outside of bui-backend. [The demo][bui-demo]
20//! includes a Rust web assembly (wasm) frontend using the
21//! [yew](https://github.com/yewstack/yew) framework, the
22//! [seed](https://github.com/seed-rs/seed) framework, and a plain Javascript
23//! frontend. Together, this lets you ship an application written in Rust as a
24//! single file with a browser-based UI.
25//!
26//! The operating principle is that the server runs an HTTP server (based on
27//! [hyper](https://hyper.rs)) to which the browser connects. The initial page
28//! tells the browser to open a connection to a [Server Sent
29//! Events](https://html.spec.whatwg.org/multipage/server-sent-events.html)
30//! endpoint and the server can subsequently push updates to the browser.
31//! Additionally, the server listens for POST callbacks on another endpoint. All
32//! data is encoded as JSON.
33//!
34//! #### Features
35//!
36//! - Uses
37//! [`async-change-tracker`](https://crates.io/crates/async-change-tracker)
38//! type to ensure that server state changes are reactively sent to all
39//! connected frontends.
40//! - To keep things simple, server state is shared with all connected clients.
41//! - Session keys (per browser) and connection keys (per tab) are maintained
42//! and allow taking control of communication using pre-established event
43//! stream. (This is an "escape hatch" to break out of the bui-backend
44//! abstractions as required by some use cases.)
45//! - Written in asynchronous rust using async/await.
46//! - Uses [Serde JSON](https://crates.io/crates/serde_json).
47//! - Compile-time choice between bundling served files into executable (with
48//! `bundle_files` feature) or reading files from disk (`serve_files`).
49//!
50//! #### Demo
51//!
52//! A demo is available with frontends written in Rust web assembly using the
53//! seed framework and plain Javascript. (Use [`bui-demo`][bui-demo] with
54//! `frontend_yew`, `frontend_seed`, or `frontend_js` feature.)
55//!
56//! #### Potential improvements
57//!
58//! - Add example with user login.
59//! - Send minimal differences when state changes, likely by improving
60//! [`async-change-tracker`](https://crates.io/crates/async-change-tracker).
61//! - Implement more sophisticated state-sharing allowing partial views and
62//! minimal updates.
63//! - Use
64//! [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
65//! instead of [`Server Sent
66//! Events`](https://caniuse.com/#search=EventSource).
67//! - Add a websocket transport option as an alternative to Server Sent Events.
68//! - Your idea here.
69//!
70//! #### Security warning
71//!
72//! Due to its nature, the program listens and responds to client connections
73//! from the network. If you expose your program to untrusted network
74//! connections, ensure that code within any callback handlers you write is safe
75//! when handling malicious input.
76//!
77//! #### Other crates in this repository
78//!
79//! - `codegen` - Buildtime codegen support for bui-backend.
80//! - `bui-demo` - Example program with Rust and Javascript frontends.
81//!
82//! ## License
83//!
84//! Licensed under either of
85//!
86//! * Apache License, Version 2.0, (./LICENSE-APACHE or
87//! http://www.apache.org/licenses/LICENSE-2.0)
88//! * MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT) at your
89//! option.
90//!
91//! ## Contribution
92//!
93//! Unless you explicitly state otherwise, any contribution intentionally
94//! submitted for inclusion in the work by you, as defined in the Apache-2.0
95//! license, shall be dual licensed as above, without any additional terms or
96//! conditions.
97//!
98//! ## Code of conduct
99//!
100//! Anyone who interacts with bui-backend in any space including but not limited
101//! to this GitHub repository is expected to follow our [code of
102//! conduct](https://github.com/astraw/bui-backend/blob/master/code_of_conduct.md).
103//!
104//! ## Operational overview
105//!
106//! ```text
107//! HTTP responses
108//! & event stream
109//! +--server----------+ +--------------> +--web-browser-------------------------+
110//! |app binary written| | frontend, optionally in written |
111//! |with bui_backend | <--------------+ | in rust with support from bui_backend|
112//! +------------------+ HTTP requests +--------------------------------------+
113//! ```
114//! <!-- ASCII art drawn with http://asciiflow.com/ -->
115//!
116//! ## Example
117//!
118//! For a full example, see [the
119//! demo](https://github.com/astraw/bui-backend/tree/master/bui-demo).
120//!
121//! ## Usage
122//!
123//! This example assumes you have the following filesystem layout in the crate
124//! for the application binary that will run the webserver:
125//!
126//! ```text
127//! .
128//! ├── build.rs # Bundles frontend files or specifies serving from disk.
129//! ├── Cargo.toml # Normal Cargo.toml manifest file.
130//! ├── frontend_js # Your frontend files are in this directory. bui_backend
131//! │ ├── index.html # also includes some assistance for writing frontends
132//! │ └── js # in rust, such as automatic serialization.
133//! │ └── main.js
134//! └── src # The source for your application binary is here.
135//! └── main.rs
136//! ```
137//!
138//! In this example, we assume you have files to serve for a frontend (e.g.
139//! `index.html`) in the directory `frontend_js`. You must create a file
140//! `build.rs` which will:
141//! * compile the files in this directory into your application's binary if you
142//! use the default compilation features or specified the `bundle_files`
143//! cargo feature (recommended for deployment),
144//! * attempt to access the files in this directory at runtime if you use the
145//! `serve_files` cargo feature (recommended for frontend development),
146//! * or throw a compile time error if you do not specify exactly one of
147//! `bundle_files` and `serve_files`.
148//!
149//! In the `Cargo.toml` file for your backend application, add the following
150//! lines:
151//! ```toml
152//! [dependencies]
153//! bui-backend = "0.7"
154//! bui-backend-types = "0.7"
155//!
156//! [build-dependencies]
157//! bui-backend-codegen = "0.1.4"
158//! ```
159//!
160//! Now, here is the example `build.rs` file:
161//! ```ignore
162//! extern crate bui_backend_codegen;
163//!
164//! fn main() {
165//! bui_backend_codegen::codegen("frontend_js", "public.rs").expect("codegen failed");
166//! }
167//! ```
168//!
169//! Finally, in your `main.rs` file:
170//! ```ignore
171//! // Include the files to be served and define `fn get_default_config()`.
172//! include!(concat!(env!("OUT_DIR"), "/public.rs")); // Despite slash, this works on Windows.
173//! ```
174//!
175//! ## Building the documentation
176//!
177//! ```text
178//! RUSTDOCFLAGS='--cfg=docsrs -Dwarnings' cargo +nightly doc --open --features "bui-backend-types/uuid-v4"
179//! ```
180//!
181//! ## Testing
182//!
183//! ```text
184//! cargo +nightly test --features "bui-backend-types/uuid-v4"
185//! ```
186//!
187//! ## Regnerate README.md
188//!
189//! ```text
190//! cargo readme > README.md
191//! ```
192
193#![cfg_attr(docsrs, feature(doc_cfg))]
194#![deny(missing_docs)]
195
196#[macro_use]
197extern crate log;
198
199mod errors;
200pub use errors::Error;
201
202pub mod access_control;
203pub use access_control::AccessControl;
204
205pub mod highlevel;
206pub mod lowlevel;
207
208pub use lowlevel::CallbackHandler;