webview_bundle_protocol/
mime_type.rs1use std::fmt;
8
9const MIMETYPE_PLAIN: &str = "text/plain";
10
11pub enum MimeType {
13 Css,
14 Csv,
15 Html,
16 Ico,
17 Js,
18 Json,
19 Jsonld,
20 Mp4,
21 OctetStream,
22 Rtf,
23 Svg,
24 Txt,
25}
26
27impl fmt::Display for MimeType {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 let mime = match self {
30 MimeType::Css => "text/css",
31 MimeType::Csv => "text/csv",
32 MimeType::Html => "text/html",
33 MimeType::Ico => "image/vnd.microsoft.icon",
34 MimeType::Js => "text/javascript",
35 MimeType::Json => "application/json",
36 MimeType::Jsonld => "application/ld+json",
37 MimeType::Mp4 => "video/mp4",
38 MimeType::OctetStream => "application/octet-stream",
39 MimeType::Rtf => "application/rtf",
40 MimeType::Svg => "image/svg+xml",
41 MimeType::Txt => MIMETYPE_PLAIN,
42 };
43 write!(f, "{mime}")
44 }
45}
46
47impl MimeType {
48 pub fn parse_from_uri(uri: &str) -> MimeType {
50 Self::parse_from_uri_with_fallback(uri, Self::Html)
51 }
52
53 pub fn parse_from_uri_with_fallback(uri: &str, fallback: MimeType) -> MimeType {
55 let suffix = uri.split('.').next_back();
56 match suffix {
57 Some("bin") => Self::OctetStream,
58 Some("css" | "less" | "sass" | "styl") => Self::Css,
59 Some("csv") => Self::Csv,
60 Some("html") => Self::Html,
61 Some("ico") => Self::Ico,
62 Some("js") | Some("mjs") => Self::Js,
63 Some("json") => Self::Json,
64 Some("jsonld") => Self::Jsonld,
65 Some("mp4") => Self::Mp4,
66 Some("rtf") => Self::Rtf,
67 Some("svg") => Self::Svg,
68 Some("txt") => Self::Txt,
69 Some(_) => fallback,
71 None => Self::OctetStream,
74 }
75 }
76
77 pub fn parse(content: &[u8], uri: &str) -> String {
79 Self::parse_with_fallback(content, uri, Self::Html)
80 }
81
82 pub fn parse_with_fallback(content: &[u8], uri: &str, fallback: MimeType) -> String {
84 let mime = if uri.ends_with(".svg") {
85 None
87 } else {
88 infer::get(content).map(|info| info.mime_type())
89 };
90
91 match mime {
92 Some(mime) if mime == MIMETYPE_PLAIN => {
93 Self::parse_from_uri_with_fallback(uri, fallback).to_string()
94 }
95 None => Self::parse_from_uri_with_fallback(uri, fallback).to_string(),
96 Some(mime) => mime.to_string(),
97 }
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn parse_mime_types() {
107 let css = MimeType::parse_from_uri(
108 "https://unpkg.com/browse/bootstrap@4.1.0/dist/css/bootstrap-grid.css",
109 )
110 .to_string();
111 assert_eq!(css, "text/css".to_string());
112
113 let csv: String = MimeType::parse_from_uri("https://example.com/random.csv").to_string();
114 assert_eq!(csv, "text/csv".to_string());
115
116 let ico: String =
117 MimeType::parse_from_uri("https://icons.duckduckgo.com/ip3/microsoft.com.ico").to_string();
118 assert_eq!(ico, String::from("image/vnd.microsoft.icon"));
119
120 let html: String = MimeType::parse_from_uri("https://tauri.app/index.html").to_string();
121 assert_eq!(html, String::from("text/html"));
122
123 let js: String =
124 MimeType::parse_from_uri("https://unpkg.com/react@17.0.1/umd/react.production.min.js")
125 .to_string();
126 assert_eq!(js, "text/javascript".to_string());
127
128 let json: String =
129 MimeType::parse_from_uri("https://unpkg.com/browse/react@17.0.1/build-info.json").to_string();
130 assert_eq!(json, String::from("application/json"));
131
132 let jsonld: String = MimeType::parse_from_uri("https:/example.com/hello.jsonld").to_string();
133 assert_eq!(jsonld, String::from("application/ld+json"));
134
135 let mjs: String = MimeType::parse_from_uri("https://example.com/bundled.mjs").to_string();
136 assert_eq!(mjs, String::from("text/javascript"));
137
138 let mp4: String = MimeType::parse_from_uri("https://example.com/video.mp4").to_string();
139 assert_eq!(mp4, String::from("video/mp4"));
140
141 let rtf: String = MimeType::parse_from_uri("https://example.com/document.rtf").to_string();
142 assert_eq!(rtf, String::from("application/rtf"));
143
144 let svg: String = MimeType::parse_from_uri("https://example.com/picture.svg").to_string();
145 assert_eq!(svg, String::from("image/svg+xml"));
146
147 let txt: String = MimeType::parse_from_uri("https://example.com/file.txt").to_string();
148 assert_eq!(txt, String::from("text/plain"));
149
150 let custom_scheme1 = MimeType::parse_from_uri("wry://tauri.app").to_string();
151 assert_eq!(custom_scheme1, String::from("text/html"));
152
153 let custom_scheme2 = MimeType::parse_from_uri("wry://tauri.app/some/path").to_string();
154 assert_eq!(custom_scheme2, String::from("text/html"));
155 }
156}