vfs_https/
lib.rs

1//!
2//! Exposes a [Virtual File Systems (VFS)](https://docs.rs/vfs/) via HTTPS.
3//!
4//! The [HttpsFSServer] exposes a VFS (implementing [FileSystem](vfs::filesystem::FileSystem)) via HTTPS.
5//! [HttpsFS] can be uses to access a [FileSystem](vfs::filesystem::FileSystem) exposed by a [HttpsFSServer].
6//!
7//! # Example
8//!
9//! The two examples show the usage of a [HttpsFSServer] and a [HttpsFS]. It is assumed, that the
10//! examples are executed in the crate root. Therefore, you can find the referenced files in the
11//! crate repository.
12//!
13//! **Please note**, that it is assumed, that the used certificate is issued for "localhost".
14//!
15//! You can run the server side examples from the repository root with:
16//! ```console
17//! cargo run --example https_fs_server
18//! ```
19//!
20//! Start the client side example in another terminal with:
21//!
22//! ```console
23//! cargo run --example https_fs
24//! ```
25//!
26//! ## Server side
27//!
28//! This example exposes a [memory file system](vfs::MemoryFS) via HTTPS. The content of the file system
29//! is lost as soon as the server is terminated.
30//!
31//! ```no_run
32//! # use vfs::MemoryFS;
33//! # use vfs_https::{HttpsFSResult, HttpsFSServer};
34//! #
35//! # fn main() -> HttpsFSResult<()> {
36//! // Create a file system, which the server uses to access the files.
37//! let fs = MemoryFS::new();
38//!
39//! let server = HttpsFSServer::builder(fs)
40//!     // Since this test will not be executed as super user, we are not allowed to listen on
41//!     // a TCP port below 1000, such as the https port 443. Therefore we use a different port.
42//!     .set_port(8443)
43//!     // It is a https server, therefore we need to load a certificate, which the server
44//!     // uses. For the example we use a self signed certificate. If you want to know how to
45//!     // create a self signed certificate, see "/examples/cert/create.sh".
46//!     .load_certificates("examples/cert/cert.crt")
47//!     // We also need to load the private key, which belongs to the certificate.
48//!     .load_private_key("examples/cert/private-key.key")
49//!     // The server needs to authenticate the clients. Therefore we have to provide a method
50//!     // which // validates the user credentials. In this example, only the username 'user'
51//!     // and the password 'pass' is accepted.
52//!     // As authentication process, the 'Basic' method as defined by the
53//!     // [RFC7617](https://tools.ietf.org/html/rfc7617) is used.
54//!     .set_credential_validator(|username: &str, password: &str| {
55//!         username == "user" && password == "pass"
56//!     });
57//!
58//! // Run the server. This call is blocking.
59//! server.run()
60//! # }
61//! ```
62//!
63//! ## Client side
64//!
65//! This example connects to a [HttpsFSServer] and creates a file "example.txt" if it does not exists and appends a
66//! new line to it. Afterwards it reads the whole file and prints the content to stdout.
67//! As long as the server is not restarted, the output of this program will change with each call.
68//!
69//! For the usage of [FileSystem](vfs::filesystem::FileSystem) see the crate [vfs].
70//! The crate [chrono] is used for the generation of the time stamp.
71//!
72//! ```no_run
73//! # use chrono::prelude::*;
74//! # use std::io::Read;
75//! # use vfs::VfsPath;
76//! # use vfs_https::HttpsFS;
77//! #
78//! # fn main() -> vfs::VfsResult<()> {
79//! // You can not access the server from a different host, since the used certificate is issued
80//! // for the localhost and you have to use https://localhost:8443 to access the server. You can
81//! // also not use IPs, i.g. https://127.0.0.1:8443, since we didn't issue the certificate
82//! // for the IP.
83//! let builder = HttpsFS::builder("localhost")
84//!     // Set the port used by the server. The default is 443.
85//!     .set_port(8443)
86//!     // Add the self signed certificate as root certificate. If we don't do this, the client
87//!     // refuses to connect to the HttpsFSServer. If the server uses a certificate issued by
88//!     // an official certificate authority, than we don't need to add an additional root
89//!     // certificate.
90//!     .add_root_certificate("examples/cert/cert.crt")
91//!     // The client will use the following method to get credentials for the authentication.
92//!     .set_credential_provider(|server_msg| {
93//!         println!(
94//!             "Server request authentification with message \"{}\".",
95//!             server_msg
96//!         );
97//!         (String::from("user"), String::from("pass"))
98//!     });
99//! let root: VfsPath = builder.build()?.into();
100//! let root = root.join("example.txt")?;
101//!
102//! // make sure that the file exists
103//! if !root.exists()? {
104//!     root.create_file()?;
105//! }
106//!
107//! // add a new line to the file
108//! let mut file = root.append_file()?;
109//! let time = Local::now();
110//! let line = format!("{}: Hello HttpsFS!\n", time);
111//! file.write(line.as_bytes())?;
112//!
113//! // open file reading
114//! let file = root.open_file()?;
115//!
116//! // One should really use a BufReader, which reads files in chunks of 8kb.
117//! // The Read trait, issues a new request to the HttpsFSServer with each call,
118//! // even if only on byte is read. The headers of the http-protocol needs
119//! // several hundred bytes, which makes small reads inefficient.
120//! let mut buffed_file = std::io::BufReader::new(file);
121//!
122//! // read file content
123//! let mut content = String::new();
124//! buffed_file.read_to_string(&mut content)?;
125//!
126//! println!("Content of example.txt: \n{}", content);
127//! #
128//! # Ok(())
129//! # }
130//! ```
131//!
132//!
133//! # TODOs
134//! - Implement a [CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface)
135//!   version of the HttpsFSServer.
136//!     * This would allow a user to use any webserver provided by its
137//!       favorite web-hoster as an infrastructure. The advantage is, that the
138//!       web-hoster can overtake the certificate management, which is often
139//!       perceived as a liability.
140//! - Write a HttpsFS version, which can be compiled to WebAssembly
141//! - Consider to provide an non-blocking version of HttpsFS
142//! - Do version check after connecting to a HttpsFSServer
143
144#![warn(missing_docs)]
145
146mod error;
147mod httpsfs;
148mod protocol;
149mod server;
150pub use error::{HttpsFSError, HttpsFSResult};
151pub use httpsfs::{HttpsFS, HttpsFSBuilder};
152pub use server::{HttpsFSServer, HttpsFSServerBuilder};