mirror of
https://github.com/denoland/deno.git
synced 2025-09-27 12:49:10 +00:00
feat(unstable): Support data: urls (#5157)
This commit is contained in:
parent
a3282aa9ed
commit
e3319f34a6
18 changed files with 170 additions and 10 deletions
|
@ -100,7 +100,7 @@ impl SourceFileCache {
|
|||
}
|
||||
}
|
||||
|
||||
const SUPPORTED_URL_SCHEMES: [&str; 3] = ["http", "https", "file"];
|
||||
const SUPPORTED_URL_SCHEMES: [&str; 4] = ["http", "https", "file", "data"];
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SourceFileFetcher {
|
||||
|
@ -278,6 +278,7 @@ impl SourceFileFetcher {
|
|||
) -> Result<Option<SourceFile>, ErrBox> {
|
||||
let url_scheme = module_url.scheme();
|
||||
let is_local_file = url_scheme == "file";
|
||||
let is_data_url = url_scheme == "data";
|
||||
SourceFileFetcher::check_if_supported_scheme(&module_url)?;
|
||||
|
||||
// Local files are always fetched from disk bypassing cache entirely.
|
||||
|
@ -285,6 +286,10 @@ impl SourceFileFetcher {
|
|||
return self.fetch_local_file(&module_url, permissions).map(Some);
|
||||
}
|
||||
|
||||
if is_data_url {
|
||||
return extract_data_url(module_url).map(Some);
|
||||
}
|
||||
|
||||
self.fetch_cached_remote_source(&module_url, 10)
|
||||
}
|
||||
|
||||
|
@ -309,6 +314,7 @@ impl SourceFileFetcher {
|
|||
) -> Result<SourceFile, ErrBox> {
|
||||
let url_scheme = module_url.scheme();
|
||||
let is_local_file = url_scheme == "file";
|
||||
let is_data_url = url_scheme == "data";
|
||||
SourceFileFetcher::check_if_supported_scheme(&module_url)?;
|
||||
|
||||
// Local files are always fetched from disk bypassing cache entirely.
|
||||
|
@ -316,6 +322,10 @@ impl SourceFileFetcher {
|
|||
return self.fetch_local_file(&module_url, permissions);
|
||||
}
|
||||
|
||||
if is_data_url {
|
||||
return extract_data_url(module_url);
|
||||
}
|
||||
|
||||
// The file is remote, fail if `no_remote` is true.
|
||||
if no_remote {
|
||||
let e = std::io::Error::new(
|
||||
|
@ -552,6 +562,36 @@ impl SourceFileFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
fn extract_data_url(url: &Url) -> Result<SourceFile, ErrBox> {
|
||||
assert_eq!(url.scheme(), "data");
|
||||
let url_content = &url.as_str()[5..];
|
||||
let mut part_iterator = url_content.splitn(2, ',');
|
||||
|
||||
let media_type_str = part_iterator.next().unwrap();
|
||||
let data = if let Some(d) = part_iterator.next() {
|
||||
d
|
||||
} else {
|
||||
return Err(ErrBox::new("URIError", "Malformed data url, missing comma"));
|
||||
};
|
||||
|
||||
let filename = PathBuf::new();
|
||||
let (media_type, charset) = map_content_type(&filename, Some(media_type_str));
|
||||
let is_base64 = media_type_str.rsplit(';').any(|v| v == "base64");
|
||||
let bytes = if is_base64 {
|
||||
base64::decode(data)?
|
||||
} else {
|
||||
percent_encoding::percent_decode_str(data).collect::<Vec<u8>>()
|
||||
};
|
||||
|
||||
Ok(SourceFile {
|
||||
url: url.clone(),
|
||||
filename,
|
||||
types_header: None,
|
||||
media_type,
|
||||
source_code: TextDocument::new(bytes, charset),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn map_file_extension(path: &Path) -> msg::MediaType {
|
||||
match path.extension() {
|
||||
None => msg::MediaType::Unknown,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue