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
//! Serves static file assets from the file system.
//!
//! ```
//! # #[cfg(not(unix))] fn main() {}
//! # #[cfg(unix)] fn main() {
//! use trillium_static::{StaticFileHandler, crate_relative_path};
//! use trillium_testing::TestServer;
//!
//! # trillium_testing::block_on(async {
//! let handler = StaticFileHandler::new(crate_relative_path!("examples/files"))
//! .with_index_file("index.html");
//!
//! // given the following directory layout
//! //
//! // examples/files
//! // ├── index.html
//! // ├── subdir
//! // │ └── index.html
//! // └── subdir_with_no_index
//! // └── plaintext.txt
//!
//! let app = TestServer::new(handler).await;
//!
//! app.get("/")
//! .await
//! .assert_ok()
//! .assert_body("<h1>hello world</h1>\n")
//! .assert_header("content-type", "text/html; charset=utf-8");
//!
//! app.get("/file_that_does_not_exist.txt")
//! .await
//! .assert_status(404);
//!
//! app.get("/index.html").await.assert_ok();
//!
//! app.get("/subdir/index.html")
//! .await
//! .assert_ok()
//! .assert_body("subdir index.html\n");
//!
//! app.get("/subdir")
//! .await
//! .assert_ok()
//! .assert_body("subdir index.html\n");
//!
//! app.get("/subdir_with_no_index").await.assert_status(404);
//!
//! app.get("/subdir_with_no_index/plaintext.txt")
//! .await
//! .assert_ok()
//! .assert_body("plaintext file\n")
//! .assert_header("content-type", "text/plain; charset=utf-8");
//!
//! // with a different index file
//! let plaintext_index = StaticFileHandler::new(crate_relative_path!("examples/files"))
//! .with_index_file("plaintext.txt");
//!
//! let app2 = TestServer::new(plaintext_index).await;
//!
//! app2.get("/").await.assert_status(404);
//! app2.get("/subdir").await.assert_status(404);
//!
//! app2.get("/subdir_with_no_index")
//! .await
//! .assert_ok()
//! .assert_body("plaintext file\n")
//! .assert_header("content-type", "text/plain; charset=utf-8");
//! # });
//! # }
//! ```
//!
//!
//! ## ❗IMPORTANT❗
//!
//! this crate has three features currently: `smol`, `async-std`, and
//! `tokio`.
//!
//! You **must** enable one of these in order to use the crate. This
//! is intended to be a temporary situation, and eventually you will not
//! need to specify the runtime through feature flags.
//!
//! ## stability note
//!
//! Please note that this crate is fairly incomplete, while functional. It
//! does not include any notion of range requests or cache headers. It
//! serves all files from disk every time, with no in-memory caching.
pub use StaticFileHandler;
pub use relative_path;
pub use StaticConnExt;
/// a convenient helper macro to build a str relative to the crate root
/// convenience alias for [`StaticFileHandler::new`]