~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.


b6b17c21 frederikhors

3 years ago
add axum-spa example
examples/axum-spa/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /target
examples/axum-spa/Cargo.toml ADDED
@@ -0,0 +1,12 @@
1
+ [package]
2
+ name = "rust_embed_spa"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
+
8
+ [dependencies]
9
+ axum = "0.5.15"
10
+ mime_guess = "2.0.4"
11
+ rust-embed = "6.4.0"
12
+ tokio = { version = "1.20.1", features = ["full"] }
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/src/main.rs ADDED
@@ -0,0 +1,73 @@
1
+ use axum::{
2
+ body::{boxed, Full},
3
+ handler::Handler,
4
+ http::{header, StatusCode, Uri},
5
+ response::{IntoResponse, Response},
6
+ routing::Router,
7
+ };
8
+ use mime_guess;
9
+ use rust_embed::RustEmbed;
10
+ use std::net::SocketAddr;
11
+
12
+ static INDEX_HTML: &str = "index.html";
13
+
14
+ #[derive(RustEmbed)]
15
+ #[folder = "assets/"]
16
+ struct Assets;
17
+
18
+ #[tokio::main]
19
+ async fn main() {
20
+ let app = Router::new().fallback(static_handler.into_service());
21
+
22
+ let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
23
+ println!("listening on {}", addr);
24
+ axum::Server::bind(&addr)
25
+ .serve(app.into_make_service())
26
+ .await
27
+ .unwrap();
28
+ }
29
+
30
+ async fn static_handler(uri: Uri) -> impl IntoResponse {
31
+ let path = uri.path().trim_start_matches('/').to_string();
32
+
33
+ if path.is_empty() || path == INDEX_HTML {
34
+ return index_html().await.into_response();
35
+ }
36
+
37
+ match Assets::get(path.as_str()) {
38
+ Some(content) => {
39
+ let body = boxed(Full::from(content.data));
40
+ let mime = mime_guess::from_path(path).first_or_octet_stream();
41
+
42
+ Response::builder()
43
+ .header(header::CONTENT_TYPE, mime.as_ref())
44
+ .body(body)
45
+ .unwrap()
46
+ }
47
+ None => {
48
+ if path.contains('.') {
49
+ return not_found().await.into_response();
50
+ }
51
+
52
+ index_html().await.into_response()
53
+ }
54
+ }
55
+ }
56
+
57
+ async fn index_html() -> impl IntoResponse {
58
+ match Assets::get(INDEX_HTML) {
59
+ Some(content) => {
60
+ let body = boxed(Full::from(content.data));
61
+
62
+ Response::builder()
63
+ .header(header::CONTENT_TYPE, "text/html")
64
+ .body(body)
65
+ .unwrap()
66
+ }
67
+ None => not_found().await.into_response(),
68
+ }
69
+ }
70
+
71
+ async fn not_found() -> impl IntoResponse {
72
+ (StatusCode::NOT_FOUND, "404")
73
+ }