1#[cfg(feature = "https")]
5use native_tls::{Identity, TlsAcceptor};
6#[cfg(feature = "https")]
7use std::sync::Arc;
8
9use std::ffi::OsStr;
10use std::fs;
11use std::io::BufRead;
12use std::io::{Read, Write};
13use std::net::TcpListener;
14use std::path::Path;
15use std::str;
16use std::thread;
17
18#[cfg(feature = "reload")]
19mod reload;
20
21pub fn read_header<T: Read + Write>(stream: &mut T) -> Vec<u8> {
22 let mut buffer = Vec::new();
23 let mut reader = std::io::BufReader::new(stream);
24 loop {
25 reader.read_until(b'\n', &mut buffer).unwrap();
26 if buffer.ends_with(b"\r\n\r\n") {
28 break;
29 }
30 }
31 buffer
32}
33
34#[allow(unused)]
35fn handle_client<T: Read + Write>(mut stream: T, root_path: &str, reload: bool, headers: &str) {
36 let buffer = read_header(&mut stream);
37 let request_string = str::from_utf8(&buffer).unwrap();
38
39 if request_string.is_empty() {
40 return;
41 }
42
43 let mut parts = request_string.split(' ');
45
46 let _method = parts.next().unwrap().trim();
47 let mut path = parts.next().unwrap().trim();
48 let _http_version = parts.next().unwrap().trim();
49
50 if let Some(parameters_index) = path.find('?') {
52 path = &path[..parameters_index];
53 }
54
55 let path = path.replace("../", "").replace("%20", " ");
57 let path = if path.ends_with("/") {
58 Path::new(root_path).join(Path::new(&format!(
59 "{}{}",
60 path.trim_start_matches('/'),
61 "index.html"
62 )))
63 } else {
64 Path::new(root_path).join(path.trim_matches('/'))
65 };
66
67 let extension = path.extension().and_then(OsStr::to_str);
68
69 let (file_contents, extension) = if extension != None {
70 (fs::read(&path), extension)
71 } else {
72 if let Ok(file_contents) = fs::read(&path) {
74 println!("WARNING: Serving file without extension: [ {} ] with media type 'application/octet-stream'", &path.to_str().unwrap());
75 (Ok(file_contents), None)
76 } else {
77 let file = fs::read(&path.with_extension("html"));
80 (file, Some("html"))
81 }
82 };
83
84 if let Ok(mut file_contents) = file_contents {
85 let content_type = extension_to_mime_impl(extension);
87
88 #[allow(unused_mut)]
89 let mut content_length = file_contents.len();
90
91 #[cfg(feature = "reload")]
93 let reload_append = include_bytes!("reload.html");
94 #[cfg(feature = "reload")]
95 {
96 if extension == Some("html") && reload {
97 content_length += reload_append.len();
98 }
99 }
100
101 let response = format!(
102 "HTTP/1.1 200 OK\r\nContent-type: {}\r\nContent-Length: {}{}\r\n\r\n",
103 content_type, content_length, headers
104 );
105
106 let mut bytes = response.as_bytes().to_vec();
107 bytes.append(&mut file_contents);
108 stream.write_all(&bytes).unwrap();
109
110 #[cfg(feature = "reload")]
112 {
113 if extension == Some("html") && reload {
114 stream.write_all(reload_append).unwrap();
116 }
117 }
118
119 stream.flush().unwrap();
120 } else {
121 println!("Could not find file: {}", path.to_str().unwrap());
122 let response = "HTTP/1.1 404 NOT FOUND\r\n\r\n";
123 stream.write_all(response.as_bytes()).unwrap();
124 stream.flush().unwrap();
125 }
126}
127
128pub fn run(address: &str, port: u32, path: &str, reload: bool, headers: &str) {
129 #[cfg(feature = "https")]
130 let acceptor = {
131 let bytes = include_bytes!("identity.pfx");
136 let identity = Identity::from_pkcs12(bytes, "debug").unwrap();
137 Arc::new(TlsAcceptor::new(identity).unwrap())
138 };
139
140 #[cfg(feature = "reload")]
141 {
142 if reload {
143 let address = address.to_owned();
144 let path = path.to_owned();
145 thread::spawn(move || {
146 reload::watch_for_reloads(&address, &path);
147 });
148 }
149 }
150
151 let address_with_port = format!("{}:{:?}", address, port);
152 let listener = TcpListener::bind(address_with_port).unwrap();
153 for stream in listener.incoming() {
154 if let Ok(stream) = stream {
155 #[cfg(feature = "https")]
156 let acceptor = acceptor.clone();
157
158 let path = path.to_owned();
159 let headers = headers.to_owned();
160 thread::spawn(move || {
161 let mut buf = [0; 2];
165 stream.peek(&mut buf).expect("peek failed");
166
167 #[cfg(feature = "https")]
168 let is_https =
169 !((buf[0] as char).is_alphabetic() && (buf[1] as char).is_alphabetic());
170
171 #[cfg(not(feature = "https"))]
172 let is_https = false;
173
174 if is_https {
175 #[cfg(feature = "https")]
177 if let Ok(stream) = acceptor.accept(stream) {
178 handle_client(stream, &path, reload, &headers);
179 }
180 } else {
181 handle_client(stream, &path, reload, &headers);
182 }
183 });
184 }
185 }
186}
187
188fn extension_to_mime_impl(extension: Option<&str>) -> &'static str {
192 match extension {
195 Some("323") => "text/h323; charset=utf8",
196 Some("3g2") => "video/3gpp2",
197 Some("3gp") => "video/3gpp",
198 Some("3gp2") => "video/3gpp2",
199 Some("3gpp") => "video/3gpp",
200 Some("7z") => "application/x-7z-compressed",
201 Some("aa") => "audio/audible",
202 Some("aac") => "audio/aac",
203 Some("aaf") => "application/octet-stream",
204 Some("aax") => "audio/vnd.audible.aax",
205 Some("ac3") => "audio/ac3",
206 Some("aca") => "application/octet-stream",
207 Some("accda") => "application/msaccess.addin",
208 Some("accdb") => "application/msaccess",
209 Some("accdc") => "application/msaccess.cab",
210 Some("accde") => "application/msaccess",
211 Some("accdr") => "application/msaccess.runtime",
212 Some("accdt") => "application/msaccess",
213 Some("accdw") => "application/msaccess.webapplication",
214 Some("accft") => "application/msaccess.ftemplate",
215 Some("acx") => "application/internet-property-stream",
216 Some("addin") => "application/xml",
217 Some("ade") => "application/msaccess",
218 Some("adobebridge") => "application/x-bridge-url",
219 Some("adp") => "application/msaccess",
220 Some("adt") => "audio/vnd.dlna.adts",
221 Some("adts") => "audio/aac",
222 Some("afm") => "application/octet-stream",
223 Some("ai") => "application/postscript",
224 Some("aif") => "audio/x-aiff",
225 Some("aifc") => "audio/aiff",
226 Some("aiff") => "audio/aiff",
227 Some("air") => "application/vnd.adobe.air-application-installer-package+zip",
228 Some("amc") => "application/x-mpeg",
229 Some("application") => "application/x-ms-application",
230 Some("art") => "image/x-jg",
231 Some("asa") => "application/xml",
232 Some("asax") => "application/xml",
233 Some("ascx") => "application/xml",
234 Some("asd") => "application/octet-stream",
235 Some("asf") => "video/x-ms-asf",
236 Some("ashx") => "application/xml",
237 Some("asi") => "application/octet-stream",
238 Some("asm") => "text/plain; charset=utf8",
239 Some("asmx") => "application/xml",
240 Some("aspx") => "application/xml",
241 Some("asr") => "video/x-ms-asf",
242 Some("asx") => "video/x-ms-asf",
243 Some("atom") => "application/atom+xml",
244 Some("au") => "audio/basic",
245 Some("avi") => "video/x-msvideo",
246 Some("axs") => "application/olescript",
247 Some("bas") => "text/plain; charset=utf8",
248 Some("bcpio") => "application/x-bcpio",
249 Some("bin") => "application/octet-stream",
250 Some("bmp") => "image/bmp",
251 Some("c") => "text/plain; charset=utf8",
252 Some("cab") => "application/octet-stream",
253 Some("caf") => "audio/x-caf",
254 Some("calx") => "application/vnd.ms-office.calx",
255 Some("cat") => "application/vnd.ms-pki.seccat",
256 Some("cc") => "text/plain; charset=utf8",
257 Some("cd") => "text/plain; charset=utf8",
258 Some("cdda") => "audio/aiff",
259 Some("cdf") => "application/x-cdf",
260 Some("cer") => "application/x-x509-ca-cert",
261 Some("chm") => "application/octet-stream",
262 Some("class") => "application/x-java-applet",
263 Some("clp") => "application/x-msclip",
264 Some("cmx") => "image/x-cmx",
265 Some("cnf") => "text/plain; charset=utf8",
266 Some("cod") => "image/cis-cod",
267 Some("config") => "application/xml",
268 Some("contact") => "text/x-ms-contact; charset=utf8",
269 Some("coverage") => "application/xml",
270 Some("cpio") => "application/x-cpio",
271 Some("cpp") => "text/plain; charset=utf8",
272 Some("crd") => "application/x-mscardfile",
273 Some("crl") => "application/pkix-crl",
274 Some("crt") => "application/x-x509-ca-cert",
275 Some("cs") => "text/plain; charset=utf8",
276 Some("csdproj") => "text/plain; charset=utf8",
277 Some("csh") => "application/x-csh",
278 Some("csproj") => "text/plain; charset=utf8",
279 Some("css") => "text/css; charset=utf8",
280 Some("csv") => "text/csv; charset=utf8",
281 Some("cur") => "application/octet-stream",
282 Some("cxx") => "text/plain; charset=utf8",
283 Some("dat") => "application/octet-stream",
284 Some("datasource") => "application/xml",
285 Some("dbproj") => "text/plain; charset=utf8",
286 Some("dcr") => "application/x-director",
287 Some("def") => "text/plain; charset=utf8",
288 Some("deploy") => "application/octet-stream",
289 Some("der") => "application/x-x509-ca-cert",
290 Some("dgml") => "application/xml",
291 Some("dib") => "image/bmp",
292 Some("dif") => "video/x-dv",
293 Some("dir") => "application/x-director",
294 Some("disco") => "application/xml",
295 Some("dll") => "application/x-msdownload",
296 Some("dll.config") => "application/xml",
297 Some("dlm") => "text/dlm; charset=utf8",
298 Some("doc") => "application/msword",
299 Some("docm") => "application/vnd.ms-word.document.macroEnabled.12",
300 Some("docx") => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
301 Some("dot") => "application/msword",
302 Some("dotm") => "application/vnd.ms-word.template.macroEnabled.12",
303 Some("dotx") => "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
304 Some("dsp") => "application/octet-stream",
305 Some("dsw") => "text/plain; charset=utf8",
306 Some("dtd") => "application/xml",
307 Some("dtsConfig") => "application/xml",
308 Some("dv") => "video/x-dv",
309 Some("dvi") => "application/x-dvi",
310 Some("dwf") => "drawing/x-dwf",
311 Some("dwp") => "application/octet-stream",
312 Some("dxr") => "application/x-director",
313 Some("eml") => "message/rfc822",
314 Some("emz") => "application/octet-stream",
315 Some("eot") => "application/vnd.ms-fontobject",
316 Some("eps") => "application/postscript",
317 Some("etl") => "application/etl",
318 Some("etx") => "text/x-setext; charset=utf8",
319 Some("evy") => "application/envoy",
320 Some("exe") => "application/octet-stream",
321 Some("exe.config") => "application/xml",
322 Some("fdf") => "application/vnd.fdf",
323 Some("fif") => "application/fractals",
324 Some("filters") => "Application/xml",
325 Some("fla") => "application/octet-stream",
326 Some("flr") => "x-world/x-vrml",
327 Some("flv") => "video/x-flv",
328 Some("fsscript") => "application/fsharp-script",
329 Some("fsx") => "application/fsharp-script",
330 Some("generictest") => "application/xml",
331 Some("gif") => "image/gif",
332 Some("group") => "text/x-ms-group; charset=utf8",
333 Some("gsm") => "audio/x-gsm",
334 Some("gtar") => "application/x-gtar",
335 Some("gz") => "application/x-gzip",
336 Some("h") => "text/plain; charset=utf8",
337 Some("hdf") => "application/x-hdf",
338 Some("hdml") => "text/x-hdml; charset=utf8",
339 Some("hhc") => "application/x-oleobject",
340 Some("hhk") => "application/octet-stream",
341 Some("hhp") => "application/octet-stream",
342 Some("hlp") => "application/winhlp",
343 Some("hpp") => "text/plain; charset=utf8",
344 Some("hqx") => "application/mac-binhex40",
345 Some("hta") => "application/hta",
346 Some("htc") => "text/x-component; charset=utf8",
347 Some("htm") => "text/html; charset=utf8",
348 Some("html") => "text/html; charset=utf8",
349 Some("htt") => "text/webviewhtml; charset=utf8",
350 Some("hxa") => "application/xml",
351 Some("hxc") => "application/xml",
352 Some("hxd") => "application/octet-stream",
353 Some("hxe") => "application/xml",
354 Some("hxf") => "application/xml",
355 Some("hxh") => "application/octet-stream",
356 Some("hxi") => "application/octet-stream",
357 Some("hxk") => "application/xml",
358 Some("hxq") => "application/octet-stream",
359 Some("hxr") => "application/octet-stream",
360 Some("hxs") => "application/octet-stream",
361 Some("hxt") => "text/html; charset=utf8",
362 Some("hxv") => "application/xml",
363 Some("hxw") => "application/octet-stream",
364 Some("hxx") => "text/plain; charset=utf8",
365 Some("i") => "text/plain; charset=utf8",
366 Some("ico") => "image/x-icon",
367 Some("ics") => "application/octet-stream",
368 Some("idl") => "text/plain; charset=utf8",
369 Some("ief") => "image/ief",
370 Some("iii") => "application/x-iphone",
371 Some("inc") => "text/plain; charset=utf8",
372 Some("inf") => "application/octet-stream",
373 Some("inl") => "text/plain; charset=utf8",
374 Some("ins") => "application/x-internet-signup",
375 Some("ipa") => "application/x-itunes-ipa",
376 Some("ipg") => "application/x-itunes-ipg",
377 Some("ipproj") => "text/plain; charset=utf8",
378 Some("ipsw") => "application/x-itunes-ipsw",
379 Some("iqy") => "text/x-ms-iqy; charset=utf8",
380 Some("isp") => "application/x-internet-signup",
381 Some("ite") => "application/x-itunes-ite",
382 Some("itlp") => "application/x-itunes-itlp",
383 Some("itms") => "application/x-itunes-itms",
384 Some("itpc") => "application/x-itunes-itpc",
385 Some("ivf") => "video/x-ivf",
386 Some("jar") => "application/java-archive",
387 Some("java") => "application/octet-stream",
388 Some("jck") => "application/liquidmotion",
389 Some("jcz") => "application/liquidmotion",
390 Some("jfif") => "image/pjpeg",
391 Some("jnlp") => "application/x-java-jnlp-file",
392 Some("jpb") => "application/octet-stream",
393 Some("jpe") => "image/jpeg",
394 Some("jpeg") => "image/jpeg",
395 Some("jpg") => "image/jpeg",
396 Some("js") => "application/javascript",
397 Some("json") => "application/json",
398 Some("jsx") => "text/jscript; charset=utf8",
399 Some("jsxbin") => "text/plain; charset=utf8",
400 Some("latex") => "application/x-latex",
401 Some("library-ms") => "application/windows-library+xml",
402 Some("lit") => "application/x-ms-reader",
403 Some("loadtest") => "application/xml",
404 Some("lpk") => "application/octet-stream",
405 Some("lsf") => "video/x-la-asf",
406 Some("lst") => "text/plain; charset=utf8",
407 Some("lsx") => "video/x-la-asf",
408 Some("lzh") => "application/octet-stream",
409 Some("m13") => "application/x-msmediaview",
410 Some("m14") => "application/x-msmediaview",
411 Some("m1v") => "video/mpeg",
412 Some("m2t") => "video/vnd.dlna.mpeg-tts",
413 Some("m2ts") => "video/vnd.dlna.mpeg-tts",
414 Some("m2v") => "video/mpeg",
415 Some("m3u") => "audio/x-mpegurl",
416 Some("m3u8") => "audio/x-mpegurl",
417 Some("m4a") => "audio/m4a",
418 Some("m4b") => "audio/m4b",
419 Some("m4p") => "audio/m4p",
420 Some("m4r") => "audio/x-m4r",
421 Some("m4v") => "video/x-m4v",
422 Some("mac") => "image/x-macpaint",
423 Some("mak") => "text/plain; charset=utf8",
424 Some("man") => "application/x-troff-man",
425 Some("manifest") => "application/x-ms-manifest",
426 Some("map") => "text/plain; charset=utf8",
427 Some("master") => "application/xml",
428 Some("mda") => "application/msaccess",
429 Some("mdb") => "application/x-msaccess",
430 Some("mde") => "application/msaccess",
431 Some("mdp") => "application/octet-stream",
432 Some("me") => "application/x-troff-me",
433 Some("mfp") => "application/x-shockwave-flash",
434 Some("mht") => "message/rfc822",
435 Some("mhtml") => "message/rfc822",
436 Some("mid") => "audio/mid",
437 Some("midi") => "audio/mid",
438 Some("mix") => "application/octet-stream",
439 Some("mjs") => "application/javascript",
440 Some("mk") => "text/plain; charset=utf8",
441 Some("mmf") => "application/x-smaf",
442 Some("mno") => "application/xml",
443 Some("mny") => "application/x-msmoney",
444 Some("mod") => "video/mpeg",
445 Some("mov") => "video/quicktime",
446 Some("movie") => "video/x-sgi-movie",
447 Some("mp2") => "video/mpeg",
448 Some("mp2v") => "video/mpeg",
449 Some("mp3") => "audio/mpeg",
450 Some("mp4") => "video/mp4",
451 Some("mp4v") => "video/mp4",
452 Some("mpa") => "video/mpeg",
453 Some("mpe") => "video/mpeg",
454 Some("mpeg") => "video/mpeg",
455 Some("mpf") => "application/vnd.ms-mediapackage",
456 Some("mpg") => "video/mpeg",
457 Some("mpp") => "application/vnd.ms-project",
458 Some("mpv2") => "video/mpeg",
459 Some("mqv") => "video/quicktime",
460 Some("ms") => "application/x-troff-ms",
461 Some("msi") => "application/octet-stream",
462 Some("mso") => "application/octet-stream",
463 Some("mts") => "video/vnd.dlna.mpeg-tts",
464 Some("mtx") => "application/xml",
465 Some("mvb") => "application/x-msmediaview",
466 Some("mvc") => "application/x-miva-compiled",
467 Some("mxp") => "application/x-mmxp",
468 Some("nc") => "application/x-netcdf",
469 Some("nsc") => "video/x-ms-asf",
470 Some("nws") => "message/rfc822",
471 Some("ocx") => "application/octet-stream",
472 Some("oda") => "application/oda",
473 Some("odc") => "text/x-ms-odc; charset=utf8",
474 Some("odh") => "text/plain; charset=utf8",
475 Some("odl") => "text/plain; charset=utf8",
476 Some("odp") => "application/vnd.oasis.opendocument.presentation",
477 Some("ods") => "application/oleobject",
478 Some("odt") => "application/vnd.oasis.opendocument.text",
479 Some("ogg") => "application/ogg",
480 Some("one") => "application/onenote",
481 Some("onea") => "application/onenote",
482 Some("onepkg") => "application/onenote",
483 Some("onetmp") => "application/onenote",
484 Some("onetoc") => "application/onenote",
485 Some("onetoc2") => "application/onenote",
486 Some("orderedtest") => "application/xml",
487 Some("osdx") => "application/opensearchdescription+xml",
488 Some("otf") => "application/x-font-opentype",
489 Some("p10") => "application/pkcs10",
490 Some("p12") => "application/x-pkcs12",
491 Some("p7b") => "application/x-pkcs7-certificates",
492 Some("p7c") => "application/pkcs7-mime",
493 Some("p7m") => "application/pkcs7-mime",
494 Some("p7r") => "application/x-pkcs7-certreqresp",
495 Some("p7s") => "application/pkcs7-signature",
496 Some("pbm") => "image/x-portable-bitmap",
497 Some("pcast") => "application/x-podcast",
498 Some("pct") => "image/pict",
499 Some("pcx") => "application/octet-stream",
500 Some("pcz") => "application/octet-stream",
501 Some("pdf") => "application/pdf",
502 Some("pfb") => "application/octet-stream",
503 Some("pfm") => "application/octet-stream",
504 Some("pfx") => "application/x-pkcs12",
505 Some("pgm") => "image/x-portable-graymap",
506 Some("pic") => "image/pict",
507 Some("pict") => "image/pict",
508 Some("pkgdef") => "text/plain; charset=utf8",
509 Some("pkgundef") => "text/plain; charset=utf8",
510 Some("pko") => "application/vnd.ms-pki.pko",
511 Some("pls") => "audio/scpls",
512 Some("pma") => "application/x-perfmon",
513 Some("pmc") => "application/x-perfmon",
514 Some("pml") => "application/x-perfmon",
515 Some("pmr") => "application/x-perfmon",
516 Some("pmw") => "application/x-perfmon",
517 Some("png") => "image/png",
518 Some("pnm") => "image/x-portable-anymap",
519 Some("pnt") => "image/x-macpaint",
520 Some("pntg") => "image/x-macpaint",
521 Some("pnz") => "image/png",
522 Some("pot") => "application/vnd.ms-powerpoint",
523 Some("potm") => "application/vnd.ms-powerpoint.template.macroEnabled.12",
524 Some("potx") => "application/vnd.openxmlformats-officedocument.presentationml.template",
525 Some("ppa") => "application/vnd.ms-powerpoint",
526 Some("ppam") => "application/vnd.ms-powerpoint.addin.macroEnabled.12",
527 Some("ppm") => "image/x-portable-pixmap",
528 Some("pps") => "application/vnd.ms-powerpoint",
529 Some("ppsm") => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
530 Some("ppsx") => "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
531 Some("ppt") => "application/vnd.ms-powerpoint",
532 Some("pptm") => "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
533 Some("pptx") => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
534 Some("prf") => "application/pics-rules",
535 Some("prm") => "application/octet-stream",
536 Some("prx") => "application/octet-stream",
537 Some("ps") => "application/postscript",
538 Some("psc1") => "application/PowerShell",
539 Some("psd") => "application/octet-stream",
540 Some("psess") => "application/xml",
541 Some("psm") => "application/octet-stream",
542 Some("psp") => "application/octet-stream",
543 Some("pub") => "application/x-mspublisher",
544 Some("pwz") => "application/vnd.ms-powerpoint",
545 Some("qht") => "text/x-html-insertion; charset=utf8",
546 Some("qhtm") => "text/x-html-insertion; charset=utf8",
547 Some("qt") => "video/quicktime",
548 Some("qti") => "image/x-quicktime",
549 Some("qtif") => "image/x-quicktime",
550 Some("qtl") => "application/x-quicktimeplayer",
551 Some("qxd") => "application/octet-stream",
552 Some("ra") => "audio/x-pn-realaudio",
553 Some("ram") => "audio/x-pn-realaudio",
554 Some("rar") => "application/octet-stream",
555 Some("ras") => "image/x-cmu-raster",
556 Some("rat") => "application/rat-file",
557 Some("rc") => "text/plain; charset=utf8",
558 Some("rc2") => "text/plain; charset=utf8",
559 Some("rct") => "text/plain; charset=utf8",
560 Some("rdlc") => "application/xml",
561 Some("resx") => "application/xml",
562 Some("rf") => "image/vnd.rn-realflash",
563 Some("rgb") => "image/x-rgb",
564 Some("rgs") => "text/plain; charset=utf8",
565 Some("rm") => "application/vnd.rn-realmedia",
566 Some("rmi") => "audio/mid",
567 Some("rmp") => "application/vnd.rn-rn_music_package",
568 Some("roff") => "application/x-troff",
569 Some("rpm") => "audio/x-pn-realaudio-plugin",
570 Some("rqy") => "text/x-ms-rqy; charset=utf8",
571 Some("rtf") => "application/rtf",
572 Some("rtx") => "text/richtext; charset=utf8",
573 Some("ruleset") => "application/xml",
574 Some("s") => "text/plain; charset=utf8",
575 Some("safariextz") => "application/x-safari-safariextz",
576 Some("scd") => "application/x-msschedule",
577 Some("sct") => "text/scriptlet; charset=utf8",
578 Some("sd2") => "audio/x-sd2",
579 Some("sdp") => "application/sdp",
580 Some("sea") => "application/octet-stream",
581 Some("searchConnector-ms") => "application/windows-search-connector+xml",
582 Some("setpay") => "application/set-payment-initiation",
583 Some("setreg") => "application/set-registration-initiation",
584 Some("settings") => "application/xml",
585 Some("sfnt") => "application/font-sfnt",
586 Some("sgimb") => "application/x-sgimb",
587 Some("sgml") => "text/sgml; charset=utf8",
588 Some("sh") => "application/x-sh",
589 Some("shar") => "application/x-shar",
590 Some("shtml") => "text/html; charset=utf8",
591 Some("sit") => "application/x-stuffit",
592 Some("sitemap") => "application/xml",
593 Some("skin") => "application/xml",
594 Some("sldm") => "application/vnd.ms-powerpoint.slide.macroEnabled.12",
595 Some("sldx") => "application/vnd.openxmlformats-officedocument.presentationml.slide",
596 Some("slk") => "application/vnd.ms-excel",
597 Some("sln") => "text/plain; charset=utf8",
598 Some("slupkg-ms") => "application/x-ms-license",
599 Some("smd") => "audio/x-smd",
600 Some("smi") => "application/octet-stream",
601 Some("smx") => "audio/x-smd",
602 Some("smz") => "audio/x-smd",
603 Some("snd") => "audio/basic",
604 Some("snippet") => "application/xml",
605 Some("snp") => "application/octet-stream",
606 Some("sol") => "text/plain; charset=utf8",
607 Some("sor") => "text/plain; charset=utf8",
608 Some("spc") => "application/x-pkcs7-certificates",
609 Some("spl") => "application/futuresplash",
610 Some("src") => "application/x-wais-source",
611 Some("srf") => "text/plain; charset=utf8",
612 Some("ssisdeploymentmanifest") => "application/xml",
613 Some("ssm") => "application/streamingmedia",
614 Some("sst") => "application/vnd.ms-pki.certstore",
615 Some("stl") => "application/vnd.ms-pki.stl",
616 Some("sv4cpio") => "application/x-sv4cpio",
617 Some("sv4crc") => "application/x-sv4crc",
618 Some("svc") => "application/xml",
619 Some("svg") => "image/svg+xml",
620 Some("swf") => "application/x-shockwave-flash",
621 Some("t") => "application/x-troff",
622 Some("tar") => "application/x-tar",
623 Some("tcl") => "application/x-tcl",
624 Some("testrunconfig") => "application/xml",
625 Some("testsettings") => "application/xml",
626 Some("tex") => "application/x-tex",
627 Some("texi") => "application/x-texinfo",
628 Some("texinfo") => "application/x-texinfo",
629 Some("tgz") => "application/x-compressed",
630 Some("thmx") => "application/vnd.ms-officetheme",
631 Some("thn") => "application/octet-stream",
632 Some("tif") => "image/tiff",
633 Some("tiff") => "image/tiff",
634 Some("tlh") => "text/plain; charset=utf8",
635 Some("tli") => "text/plain; charset=utf8",
636 Some("toc") => "application/octet-stream",
637 Some("tr") => "application/x-troff",
638 Some("trm") => "application/x-msterminal",
639 Some("trx") => "application/xml",
640 Some("ts") => "video/vnd.dlna.mpeg-tts",
641 Some("tsv") => "text/tab-separated-values; charset=utf8",
642 Some("ttf") => "application/x-font-ttf",
643 Some("tts") => "video/vnd.dlna.mpeg-tts",
644 Some("txt") => "text/plain; charset=utf8",
645 Some("u32") => "application/octet-stream",
646 Some("uls") => "text/iuls; charset=utf8",
647 Some("user") => "text/plain; charset=utf8",
648 Some("ustar") => "application/x-ustar",
649 Some("vb") => "text/plain; charset=utf8",
650 Some("vbdproj") => "text/plain; charset=utf8",
651 Some("vbk") => "video/mpeg",
652 Some("vbproj") => "text/plain; charset=utf8",
653 Some("vbs") => "text/vbscript; charset=utf8",
654 Some("vcf") => "text/x-vcard; charset=utf8",
655 Some("vcproj") => "Application/xml",
656 Some("vcs") => "text/plain; charset=utf8",
657 Some("vcxproj") => "Application/xml",
658 Some("vddproj") => "text/plain; charset=utf8",
659 Some("vdp") => "text/plain; charset=utf8",
660 Some("vdproj") => "text/plain; charset=utf8",
661 Some("vdx") => "application/vnd.ms-visio.viewer",
662 Some("vml") => "application/xml",
663 Some("vscontent") => "application/xml",
664 Some("vsct") => "application/xml",
665 Some("vsd") => "application/vnd.visio",
666 Some("vsi") => "application/ms-vsi",
667 Some("vsix") => "application/vsix",
668 Some("vsixlangpack") => "application/xml",
669 Some("vsixmanifest") => "application/xml",
670 Some("vsmdi") => "application/xml",
671 Some("vspscc") => "text/plain; charset=utf8",
672 Some("vss") => "application/vnd.visio",
673 Some("vsscc") => "text/plain; charset=utf8",
674 Some("vssettings") => "application/xml",
675 Some("vssscc") => "text/plain; charset=utf8",
676 Some("vst") => "application/vnd.visio",
677 Some("vstemplate") => "application/xml",
678 Some("vsto") => "application/x-ms-vsto",
679 Some("vsw") => "application/vnd.visio",
680 Some("vsx") => "application/vnd.visio",
681 Some("vtx") => "application/vnd.visio",
682 Some("wasm") => "application/wasm",
683 Some("wav") => "audio/wav",
684 Some("wave") => "audio/wav",
685 Some("wax") => "audio/x-ms-wax",
686 Some("wbk") => "application/msword",
687 Some("wbmp") => "image/vnd.wap.wbmp",
688 Some("wcm") => "application/vnd.ms-works",
689 Some("wdb") => "application/vnd.ms-works",
690 Some("wdp") => "image/vnd.ms-photo",
691 Some("webarchive") => "application/x-safari-webarchive",
692 Some("webtest") => "application/xml",
693 Some("wiq") => "application/xml",
694 Some("wiz") => "application/msword",
695 Some("wks") => "application/vnd.ms-works",
696 Some("wlmp") => "application/wlmoviemaker",
697 Some("wlpginstall") => "application/x-wlpg-detect",
698 Some("wlpginstall3") => "application/x-wlpg3-detect",
699 Some("wm") => "video/x-ms-wm",
700 Some("wma") => "audio/x-ms-wma",
701 Some("wmd") => "application/x-ms-wmd",
702 Some("wmf") => "application/x-msmetafile",
703 Some("wml") => "text/vnd.wap.wml; charset=utf8",
704 Some("wmlc") => "application/vnd.wap.wmlc",
705 Some("wmls") => "text/vnd.wap.wmlscript; charset=utf8",
706 Some("wmlsc") => "application/vnd.wap.wmlscriptc",
707 Some("wmp") => "video/x-ms-wmp",
708 Some("wmv") => "video/x-ms-wmv",
709 Some("wmx") => "video/x-ms-wmx",
710 Some("wmz") => "application/x-ms-wmz",
711 Some("woff") => "application/font-woff",
712 Some("woff2") => "application/font-woff2",
713 Some("wpl") => "application/vnd.ms-wpl",
714 Some("wps") => "application/vnd.ms-works",
715 Some("wri") => "application/x-mswrite",
716 Some("wrl") => "x-world/x-vrml",
717 Some("wrz") => "x-world/x-vrml",
718 Some("wsc") => "text/scriptlet; charset=utf8",
719 Some("wsdl") => "application/xml",
720 Some("wvx") => "video/x-ms-wvx",
721 Some("x") => "application/directx",
722 Some("xaf") => "x-world/x-vrml",
723 Some("xaml") => "application/xaml+xml",
724 Some("xap") => "application/x-silverlight-app",
725 Some("xbap") => "application/x-ms-xbap",
726 Some("xbm") => "image/x-xbitmap",
727 Some("xdr") => "text/plain; charset=utf8",
728 Some("xht") => "application/xhtml+xml",
729 Some("xhtml") => "application/xhtml+xml",
730 Some("xla") => "application/vnd.ms-excel",
731 Some("xlam") => "application/vnd.ms-excel.addin.macroEnabled.12",
732 Some("xlc") => "application/vnd.ms-excel",
733 Some("xld") => "application/vnd.ms-excel",
734 Some("xlk") => "application/vnd.ms-excel",
735 Some("xll") => "application/vnd.ms-excel",
736 Some("xlm") => "application/vnd.ms-excel",
737 Some("xls") => "application/vnd.ms-excel",
738 Some("xlsb") => "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
739 Some("xlsm") => "application/vnd.ms-excel.sheet.macroEnabled.12",
740 Some("xlsx") => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
741 Some("xlt") => "application/vnd.ms-excel",
742 Some("xltm") => "application/vnd.ms-excel.template.macroEnabled.12",
743 Some("xltx") => "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
744 Some("xlw") => "application/vnd.ms-excel",
745 Some("xml") => "application/xml",
746 Some("xmta") => "application/xml",
747 Some("xof") => "x-world/x-vrml",
748 Some("xoml") => "text/plain; charset=utf8",
749 Some("xpm") => "image/x-xpixmap",
750 Some("xps") => "application/vnd.ms-xpsdocument",
751 Some("xrm-ms") => "application/xml",
752 Some("xsc") => "application/xml",
753 Some("xsd") => "application/xml",
754 Some("xsf") => "application/xml",
755 Some("xsl") => "application/xml",
756 Some("xslt") => "application/xslt+xml",
757 Some("xsn") => "application/octet-stream",
758 Some("xss") => "application/xml",
759 Some("xtp") => "application/octet-stream",
760 Some("xwd") => "image/x-xwindowdump",
761 Some("z") => "application/x-compress",
762 Some("zip") => "application/zip",
763 _ => "application/octet-stream",
764 }
765}