~repos /rust-embed

#rust#proc-macro#http

git clone https://pyrossh.dev/repos/rust-embed.git

rust macro which loads files into the rust binary at compile time during release and loads the file from the fs during dev.


ae15c131 Mark Drobnak

3 years ago
Merge pull request #184 from frederikhors/add-axum-spa-example
Cargo.toml CHANGED
@@ -31,6 +31,11 @@ name = "axum"
31
31
  path = "examples/axum.rs"
32
32
  required-features = ["axum-ex"]
33
33
 
34
+ [[example]]
35
+ name = "axum-spa"
36
+ path = "examples/axum-spa/main.rs"
37
+ required-features = ["axum-ex"]
38
+
34
39
  [[example]]
35
40
  name = "poem"
36
41
  path = "examples/poem.rs"
examples/axum-spa/README.md ADDED
@@ -0,0 +1 @@
1
+ A small example for hosting single page application (SPA) files with [axum](https://github.com/tokio-rs/axum) and [rust-embed](https://github.com/pyrossh/rust-embed).
examples/axum-spa/assets/index.html ADDED
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Single Page Application</title>
8
+ </head>
9
+
10
+ <body>
11
+ I'm the body!
12
+ <script src="./js/script.js"></script>
13
+ </body>
14
+
15
+ </html>
examples/axum-spa/assets/js/script.js ADDED
@@ -0,0 +1,3 @@
1
+ var elem = document.createElement("div");
2
+ elem.innerHTML = "I'm the JS script!<br>" + new Date();
3
+ document.body.appendChild(elem);
examples/axum-spa/main.rs ADDED
@@ -0,0 +1,63 @@
1
+ use axum::{
2
+ body::{boxed, Full},
3
+ handler::Handler,
4
+ http::{header, StatusCode, Uri},
5
+ response::Response,
6
+ routing::Router,
7
+ };
8
+ use rust_embed::RustEmbed;
9
+ use std::net::SocketAddr;
10
+
11
+ static INDEX_HTML: &str = "index.html";
12
+
13
+ #[derive(RustEmbed)]
14
+ #[folder = "examples/axum-spa/assets/"]
15
+ struct Assets;
16
+
17
+ #[tokio::main]
18
+ async fn main() {
19
+ let app = Router::new().fallback(static_handler.into_service());
20
+
21
+ let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
22
+ println!("listening on {}", addr);
23
+ axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
24
+ }
25
+
26
+ async fn static_handler(uri: Uri) -> Response {
27
+ let path = uri.path().trim_start_matches('/');
28
+
29
+ if path.is_empty() || path == INDEX_HTML {
30
+ return index_html().await;
31
+ }
32
+
33
+ match Assets::get(path) {
34
+ Some(content) => {
35
+ let body = boxed(Full::from(content.data));
36
+ let mime = mime_guess::from_path(path).first_or_octet_stream();
37
+
38
+ Response::builder().header(header::CONTENT_TYPE, mime.as_ref()).body(body).unwrap()
39
+ }
40
+ None => {
41
+ if path.contains('.') {
42
+ return not_found().await;
43
+ }
44
+
45
+ index_html().await
46
+ }
47
+ }
48
+ }
49
+
50
+ async fn index_html() -> Response {
51
+ match Assets::get(INDEX_HTML) {
52
+ Some(content) => {
53
+ let body = boxed(Full::from(content.data));
54
+
55
+ Response::builder().header(header::CONTENT_TYPE, "text/html").body(body).unwrap()
56
+ }
57
+ None => not_found().await,
58
+ }
59
+ }
60
+
61
+ async fn not_found() -> Response {
62
+ Response::builder().status(StatusCode::NOT_FOUND).body(boxed(Full::from("404"))).unwrap()
63
+ }