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
use std::borrow::Cow;
use actix_files::{Files, NamedFile};
use actix_service::fn_service;
use actix_web::dev::{HttpServiceFactory, ResourceDef, ServiceRequest, ServiceResponse};
#[derive(Debug, Clone)]
pub struct Spa {
index_file: Cow<'static, str>,
static_resources_mount: Cow<'static, str>,
static_resources_location: Cow<'static, str>,
}
impl Spa {
pub fn index_file(mut self, index_file: impl Into<Cow<'static, str>>) -> Self {
self.index_file = index_file.into();
self
}
pub fn static_resources_mount(
mut self,
static_resources_mount: impl Into<Cow<'static, str>>,
) -> Self {
self.static_resources_mount = static_resources_mount.into();
self
}
pub fn static_resources_location(
mut self,
static_resources_location: impl Into<Cow<'static, str>>,
) -> Self {
self.static_resources_location = static_resources_location.into();
self
}
pub fn finish(self) -> impl HttpServiceFactory {
let index_file = self.index_file.into_owned();
let static_resources_location = self.static_resources_location.into_owned();
let static_resources_mount = self.static_resources_mount.into_owned();
let files = {
let index_file = index_file.clone();
Files::new(&static_resources_mount, static_resources_location)
.index_file("extremely-unlikely-to-exist-!@$%^&*.txt")
.default_handler(move |req| serve_index(req, index_file.clone()))
};
SpaService { index_file, files }
}
}
#[derive(Debug)]
struct SpaService {
index_file: String,
files: Files,
}
impl HttpServiceFactory for SpaService {
fn register(self, config: &mut actix_web::dev::AppService) {
self.files.register(config);
let rdef = ResourceDef::root_prefix("");
config.register_service(
rdef,
None,
fn_service(move |req| serve_index(req, self.index_file.clone())),
None,
);
}
}
async fn serve_index(
req: ServiceRequest,
index_file: String,
) -> Result<ServiceResponse, actix_web::Error> {
log::trace!("serving default SPA page");
let (req, _) = req.into_parts();
let file = NamedFile::open_async(&index_file).await?;
let res = file.into_response(&req);
Ok(ServiceResponse::new(req, res))
}
impl Default for Spa {
fn default() -> Self {
Self {
index_file: Cow::Borrowed("./index.html"),
static_resources_mount: Cow::Borrowed("/"),
static_resources_location: Cow::Borrowed("./"),
}
}
}