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

#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(missing_docs)]

#[macro_use]
extern crate log;

mod errors;
pub use errors::Error;

pub mod access_control;
pub use access_control::AccessControl;

pub mod highlevel;
pub mod lowlevel;