Skip to content

Commit ae59da4

Browse files
committed
add method of specifying content-type for mappings
1 parent 53bf4d9 commit ae59da4

File tree

2 files changed

+40
-37
lines changed

2 files changed

+40
-37
lines changed

src/fileserver.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,15 @@ fn start_stream_process<S>(mut stream: S, mappings: Arc<Mappings>, zombie_mode:
198198
_ => 10,
199199
});
200200

201-
if let Some(asset) = mappings.get_asset(request.uri()) {
201+
let route = mappings.get_route(request.uri());
202+
203+
if let Some((asset, content_type)) = route.and_then( |r| Some((mappings.get_asset(&r.path)?, &r.content_type)) ) {
202204
let encoding = encodings.first().cloned()
203205
.unwrap_or(Encoding::Uncompressed);
204206

205-
send_data_async(stream, asset, encoding)
207+
let content_type = content_type.as_ref().map(String::clone);
208+
209+
send_data_async(stream, asset, encoding, content_type)
206210
} else {
207211
http::Response::new("HTTP/1.1 404 File not found")
208212
.write_header_async(stream)
@@ -220,7 +224,7 @@ fn start_stream_process<S>(mut stream: S, mappings: Arc<Mappings>, zombie_mode:
220224
})
221225
}
222226

223-
fn send_data_async<S>(mut stream: S, data: Arc<MappedAsset>, encoding: Encoding) -> Coro<SBResult<()>> where S: Read + Write + TcpStreamExt + 'static {
227+
fn send_data_async<S>(mut stream: S, data: Arc<dyn MappedAsset>, encoding: Encoding, content_type: Option<String>) -> Coro<SBResult<()>> where S: Read + Write + TcpStreamExt + 'static {
224228
use std::io::ErrorKind::{WouldBlock, Interrupted};
225229

226230
Coro::from(move || {
@@ -238,6 +242,10 @@ fn send_data_async<S>(mut stream: S, data: Arc<MappedAsset>, encoding: Encoding)
238242
Encoding::Deflate => res.set("Content-Encoding", "deflate"),
239243
}
240244

245+
if let Some(content_type) = content_type.as_ref() {
246+
res.set("Content-Type", content_type);
247+
}
248+
241249
let response_head = res.header_string().into_bytes();
242250
let mut read_amt = 0;
243251

src/mappings.rs

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ struct UnprocessedAsset {
3333
file_path: PathBuf,
3434
}
3535

36+
pub struct Mapping {
37+
pub path: PathBuf,
38+
pub content_type: Option<String>,
39+
}
40+
3641
pub struct Mappings {
37-
mappings: HashMap<String, PathBuf>,
42+
mappings: HashMap<String, Mapping>,
3843
imported_mappings: Vec<PathBuf>,
3944
file_cache: HashMap<PathBuf, Arc<PreprocessedAsset>>,
4045
caching_enabled: bool,
@@ -68,9 +73,10 @@ impl Mappings {
6873
where T: Into<Vec<u8>> {
6974

7075
let asset = PreprocessedAsset::process(data.into())?;
76+
let content_type = None;
7177

7278
self.file_cache.insert(key.into(), Arc::new(asset));
73-
self.mappings.insert(key.into(), key.into());
79+
self.mappings.insert(key.into(), Mapping{ path: key.into(), content_type });
7480

7581
Ok(())
7682
}
@@ -95,10 +101,23 @@ impl Mappings {
95101
let (key, value) = mapping.split_at(partition.unwrap());
96102
let (key, value) = (key.trim_end(), value[2..].trim_start());
97103

104+
// extract content type
105+
let (value, content_type) = if let Some(pos) = value.find('[') {
106+
let (value, type_start) = value.split_at(pos);
107+
let content_type = type_start[1..].split(']').next().unwrap();
108+
(value.trim(), Some(content_type.trim().into()))
109+
} else {
110+
(value, None)
111+
};
112+
98113
let path = [prefix, Path::new(value)].iter().collect();
99114

100-
println!("Adding mapping {} => {:?}", key, path);
101-
self.mappings.insert(key.to_owned(), path);
115+
if let Some(content_type) = &content_type {
116+
println!("Adding mapping {} => {:?} [{}]", key, path, content_type);
117+
} else {
118+
println!("Adding mapping {} => {:?}", key, path);
119+
}
120+
self.mappings.insert(key.to_owned(), Mapping{ path, content_type });
102121
}
103122

104123
self.imported_mappings.extend(imports.iter().map(From::from));
@@ -128,7 +147,7 @@ impl Mappings {
128147
println!("Compressing mapped assets...");
129148
let timer = Instant::now();
130149

131-
for path in self.mappings.values() {
150+
for Mapping{path, ..} in self.mappings.values() {
132151
let entry = self.file_cache.entry(path.clone());
133152

134153
if let Entry::Occupied(_) = entry { continue; }
@@ -148,26 +167,6 @@ impl Mappings {
148167
}
149168
}
150169

151-
// let compression = Compression::best();
152-
153-
// let mut enc = GzEncoder::new(Vec::new(), compression);
154-
// enc.write_all(&uncompressed_data)?;
155-
// let gzipped_data = enc.finish()?;
156-
157-
// let mut enc = DeflateEncoder::new(Vec::new(), compression);
158-
// enc.write_all(&uncompressed_data)?;
159-
// let deflated_data = enc.finish()?;
160-
161-
// println!(" {:.1}kB", uncompressed_data.len() as f32 / 2.0f32.powi(10));
162-
// println!("gzip -> {:.1}kB", gzipped_data.len() as f32 / 2.0f32.powi(10));
163-
// println!("defl -> {:.1}kB", gzipped_data.len() as f32 / 2.0f32.powi(10));
164-
165-
// entry.or_insert(Arc::new(PreprocessedAsset{
166-
// uncompressed_data,
167-
// deflated_data,
168-
// gzipped_data
169-
// }));
170-
171170
entry.or_insert(Arc::new(PreprocessedAsset::process(uncompressed_data)?));
172171
}
173172

@@ -178,22 +177,18 @@ impl Mappings {
178177
Ok(())
179178
}
180179

181-
pub fn get_route(&self, key: &str) -> Option<&PathBuf> {
180+
pub fn get_route(&self, key: &str) -> Option<&Mapping> {
182181
self.mappings.get(key)
183182
}
184183

185-
pub fn get_asset(&self, key: &str) -> Option<Arc<MappedAsset>> {
186-
let route = self.get_route(key);
187-
184+
pub fn get_asset(&self, route: &PathBuf) -> Option<Arc<MappedAsset>> {
188185
if self.caching_enabled {
189-
route.iter()
190-
.filter_map(|&k| self.file_cache.get(k))
186+
self.file_cache.get(route)
191187
.cloned()
192-
.next()
193188
.map(|a| a as Arc<MappedAsset>)
189+
194190
} else {
195-
route.cloned()
196-
.map(|file_path| Arc::new(UnprocessedAsset {file_path}) as Arc<MappedAsset>)
191+
Some(Arc::new(UnprocessedAsset {file_path: route.clone()}) as Arc<MappedAsset>)
197192
}
198193
}
199194
}

0 commit comments

Comments
 (0)