mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
chore(ext/cache): make helper functions public (#16117)
This commit is contained in:
parent
e2990be264
commit
eacd6a7f29
6 changed files with 183 additions and 113 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -943,7 +943,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_cache"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
|
|
@ -27,7 +27,7 @@ path = "./bench/lsp_bench_standalone.rs"
|
|||
|
||||
[build-dependencies]
|
||||
deno_broadcast_channel = { version = "0.65.0", path = "../ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.2.0", path = "../ext/cache" }
|
||||
deno_cache = { version = "0.3.0", path = "../ext/cache" }
|
||||
deno_console = { version = "0.71.0", path = "../ext/console" }
|
||||
deno_core = { version = "0.153.0", path = "../core" }
|
||||
deno_crypto = { version = "0.85.0", path = "../ext/crypto" }
|
||||
|
|
2
ext/cache/Cargo.toml
vendored
2
ext/cache/Cargo.toml
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_cache"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["the Deno authors"]
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
|
199
ext/cache/lib.rs
vendored
199
ext/cache/lib.rs
vendored
|
@ -20,6 +20,38 @@ use std::path::PathBuf;
|
|||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CreateCache<C: Cache + 'static>(pub Arc<dyn Fn() -> C>);
|
||||
|
||||
pub fn init<CA: Cache + 'static>(
|
||||
maybe_create_cache: Option<CreateCache<CA>>,
|
||||
) -> Extension {
|
||||
Extension::builder()
|
||||
.js(include_js_files!(
|
||||
prefix "deno:ext/cache",
|
||||
"01_cache.js",
|
||||
))
|
||||
.ops(vec![
|
||||
op_cache_storage_open::decl::<CA>(),
|
||||
op_cache_storage_has::decl::<CA>(),
|
||||
op_cache_storage_delete::decl::<CA>(),
|
||||
op_cache_put::decl::<CA>(),
|
||||
op_cache_match::decl::<CA>(),
|
||||
op_cache_delete::decl::<CA>(),
|
||||
])
|
||||
.state(move |state| {
|
||||
if let Some(create_cache) = maybe_create_cache.clone() {
|
||||
state.put(create_cache);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
pub fn get_declaration() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_cache.d.ts")
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CachePutRequest {
|
||||
|
@ -181,34 +213,151 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CreateCache<C: Cache + 'static>(pub Arc<dyn Fn() -> C>);
|
||||
/// Check if headers, mentioned in the vary header, of query request
|
||||
/// and cached request are equal.
|
||||
pub fn vary_header_matches(
|
||||
vary_header: &ByteString,
|
||||
query_request_headers: &[(ByteString, ByteString)],
|
||||
cached_request_headers: &[(ByteString, ByteString)],
|
||||
) -> bool {
|
||||
let vary_header = match std::str::from_utf8(vary_header) {
|
||||
Ok(vary_header) => vary_header,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let headers = get_headers_from_vary_header(vary_header);
|
||||
for header in headers {
|
||||
let query_header = get_header(&header, query_request_headers);
|
||||
let cached_header = get_header(&header, cached_request_headers);
|
||||
if query_header != cached_header {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn init<CA: Cache + 'static>(
|
||||
maybe_create_cache: Option<CreateCache<CA>>,
|
||||
) -> Extension {
|
||||
Extension::builder()
|
||||
.js(include_js_files!(
|
||||
prefix "deno:ext/cache",
|
||||
"01_cache.js",
|
||||
))
|
||||
.ops(vec![
|
||||
op_cache_storage_open::decl::<CA>(),
|
||||
op_cache_storage_has::decl::<CA>(),
|
||||
op_cache_storage_delete::decl::<CA>(),
|
||||
op_cache_put::decl::<CA>(),
|
||||
op_cache_match::decl::<CA>(),
|
||||
op_cache_delete::decl::<CA>(),
|
||||
])
|
||||
.state(move |state| {
|
||||
if let Some(create_cache) = maybe_create_cache.clone() {
|
||||
state.put(create_cache);
|
||||
#[test]
|
||||
fn test_vary_header_matches() {
|
||||
let vary_header = ByteString::from("accept-encoding");
|
||||
let query_request_headers = vec![(
|
||||
ByteString::from("accept-encoding"),
|
||||
ByteString::from("gzip"),
|
||||
)];
|
||||
let cached_request_headers = vec![(
|
||||
ByteString::from("accept-encoding"),
|
||||
ByteString::from("gzip"),
|
||||
)];
|
||||
assert!(vary_header_matches(
|
||||
&vary_header,
|
||||
&query_request_headers,
|
||||
&cached_request_headers
|
||||
));
|
||||
let vary_header = ByteString::from("accept-encoding");
|
||||
let query_request_headers = vec![(
|
||||
ByteString::from("accept-encoding"),
|
||||
ByteString::from("gzip"),
|
||||
)];
|
||||
let cached_request_headers =
|
||||
vec![(ByteString::from("accept-encoding"), ByteString::from("br"))];
|
||||
assert!(!vary_header_matches(
|
||||
&vary_header,
|
||||
&query_request_headers,
|
||||
&cached_request_headers
|
||||
));
|
||||
}
|
||||
|
||||
/// Get headers from the vary header.
|
||||
pub fn get_headers_from_vary_header(vary_header: &str) -> Vec<String> {
|
||||
vary_header
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_lowercase())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_headers_from_vary_header() {
|
||||
let headers = get_headers_from_vary_header("accept-encoding");
|
||||
assert_eq!(headers, vec!["accept-encoding"]);
|
||||
let headers = get_headers_from_vary_header("accept-encoding, user-agent");
|
||||
assert_eq!(headers, vec!["accept-encoding", "user-agent"]);
|
||||
}
|
||||
|
||||
/// Get value for the header with the given name.
|
||||
pub fn get_header(
|
||||
name: &str,
|
||||
headers: &[(ByteString, ByteString)],
|
||||
) -> Option<ByteString> {
|
||||
headers
|
||||
.iter()
|
||||
.find(|(k, _)| {
|
||||
if let Ok(k) = std::str::from_utf8(k) {
|
||||
k.eq_ignore_ascii_case(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.build()
|
||||
.map(|(_, v)| v.to_owned())
|
||||
}
|
||||
|
||||
pub fn get_declaration() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_cache.d.ts")
|
||||
#[test]
|
||||
fn test_get_header() {
|
||||
let headers = vec![
|
||||
(
|
||||
ByteString::from("accept-encoding"),
|
||||
ByteString::from("gzip"),
|
||||
),
|
||||
(
|
||||
ByteString::from("content-type"),
|
||||
ByteString::from("application/json"),
|
||||
),
|
||||
(
|
||||
ByteString::from("vary"),
|
||||
ByteString::from("accept-encoding"),
|
||||
),
|
||||
];
|
||||
let value = get_header("accept-encoding", &headers);
|
||||
assert_eq!(value, Some(ByteString::from("gzip")));
|
||||
let value = get_header("content-type", &headers);
|
||||
assert_eq!(value, Some(ByteString::from("application/json")));
|
||||
let value = get_header("vary", &headers);
|
||||
assert_eq!(value, Some(ByteString::from("accept-encoding")));
|
||||
}
|
||||
|
||||
/// Serialize headers into bytes.
|
||||
pub fn serialize_headers(headers: &[(ByteString, ByteString)]) -> Vec<u8> {
|
||||
let mut serialized_headers = Vec::new();
|
||||
for (name, value) in headers {
|
||||
serialized_headers.extend_from_slice(name);
|
||||
serialized_headers.extend_from_slice(b"\r\n");
|
||||
serialized_headers.extend_from_slice(value);
|
||||
serialized_headers.extend_from_slice(b"\r\n");
|
||||
}
|
||||
serialized_headers
|
||||
}
|
||||
|
||||
/// Deserialize bytes into headers.
|
||||
pub fn deserialize_headers(
|
||||
serialized_headers: &[u8],
|
||||
) -> Vec<(ByteString, ByteString)> {
|
||||
let mut headers = Vec::new();
|
||||
let mut piece = None;
|
||||
let mut start = 0;
|
||||
for (i, byte) in serialized_headers.iter().enumerate() {
|
||||
if byte == &b'\r' && serialized_headers.get(i + 1) == Some(&b'\n') {
|
||||
if piece.is_none() {
|
||||
piece = Some(start..i);
|
||||
} else {
|
||||
let name = piece.unwrap();
|
||||
let value = start..i;
|
||||
headers.push((
|
||||
ByteString::from(&serialized_headers[name]),
|
||||
ByteString::from(&serialized_headers[value]),
|
||||
));
|
||||
piece = None;
|
||||
}
|
||||
start = i + 2;
|
||||
}
|
||||
}
|
||||
assert!(piece.is_none());
|
||||
assert_eq!(start, serialized_headers.len());
|
||||
headers
|
||||
}
|
||||
|
|
87
ext/cache/sqlite.rs
vendored
87
ext/cache/sqlite.rs
vendored
|
@ -21,6 +21,10 @@ use std::sync::Arc;
|
|||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
use crate::deserialize_headers;
|
||||
use crate::get_header;
|
||||
use crate::serialize_headers;
|
||||
use crate::vary_header_matches;
|
||||
use crate::Cache;
|
||||
use crate::CacheDeleteRequest;
|
||||
use crate::CacheMatchRequest;
|
||||
|
@ -328,51 +332,6 @@ fn get_responses_dir(cache_storage_dir: PathBuf, cache_id: i64) -> PathBuf {
|
|||
.join("responses")
|
||||
}
|
||||
|
||||
/// Check if the headers provided in the vary_header match
|
||||
/// the query request headers and the cached request headers.
|
||||
fn vary_header_matches(
|
||||
vary_header: &ByteString,
|
||||
query_request_headers: &[(ByteString, ByteString)],
|
||||
cached_request_headers: &[(ByteString, ByteString)],
|
||||
) -> bool {
|
||||
let vary_header = match std::str::from_utf8(vary_header) {
|
||||
Ok(vary_header) => vary_header,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let headers = get_headers_from_vary_header(vary_header);
|
||||
for header in headers {
|
||||
let query_header = get_header(&header, query_request_headers);
|
||||
let cached_header = get_header(&header, cached_request_headers);
|
||||
if query_header != cached_header {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn get_headers_from_vary_header(vary_header: &str) -> Vec<String> {
|
||||
vary_header
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_lowercase())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_header(
|
||||
name: &str,
|
||||
headers: &[(ByteString, ByteString)],
|
||||
) -> Option<ByteString> {
|
||||
headers
|
||||
.iter()
|
||||
.find(|(k, _)| {
|
||||
if let Ok(k) = std::str::from_utf8(k) {
|
||||
k.eq_ignore_ascii_case(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.map(|(_, v)| v.to_owned())
|
||||
}
|
||||
|
||||
impl deno_core::Resource for SqliteBackedCache {
|
||||
fn name(&self) -> std::borrow::Cow<str> {
|
||||
"SqliteBackedCache".into()
|
||||
|
@ -463,41 +422,3 @@ pub fn hash(token: &str) -> String {
|
|||
use sha2::Digest;
|
||||
format!("{:x}", sha2::Sha256::digest(token.as_bytes()))
|
||||
}
|
||||
|
||||
fn serialize_headers(headers: &[(ByteString, ByteString)]) -> Vec<u8> {
|
||||
let mut serialized_headers = Vec::new();
|
||||
for (name, value) in headers {
|
||||
serialized_headers.extend_from_slice(name);
|
||||
serialized_headers.extend_from_slice(b"\r\n");
|
||||
serialized_headers.extend_from_slice(value);
|
||||
serialized_headers.extend_from_slice(b"\r\n");
|
||||
}
|
||||
serialized_headers
|
||||
}
|
||||
|
||||
fn deserialize_headers(
|
||||
serialized_headers: &[u8],
|
||||
) -> Vec<(ByteString, ByteString)> {
|
||||
let mut headers = Vec::new();
|
||||
let mut piece = None;
|
||||
let mut start = 0;
|
||||
for (i, byte) in serialized_headers.iter().enumerate() {
|
||||
if byte == &b'\r' && serialized_headers.get(i + 1) == Some(&b'\n') {
|
||||
if piece.is_none() {
|
||||
piece = Some(start..i);
|
||||
} else {
|
||||
let name = piece.unwrap();
|
||||
let value = start..i;
|
||||
headers.push((
|
||||
ByteString::from(&serialized_headers[name]),
|
||||
ByteString::from(&serialized_headers[value]),
|
||||
));
|
||||
piece = None;
|
||||
}
|
||||
start = i + 2;
|
||||
}
|
||||
}
|
||||
assert!(piece.is_none());
|
||||
assert_eq!(start, serialized_headers.len());
|
||||
headers
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ path = "examples/hello_runtime.rs"
|
|||
|
||||
[build-dependencies]
|
||||
deno_broadcast_channel = { version = "0.65.0", path = "../ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.2.0", path = "../ext/cache" }
|
||||
deno_cache = { version = "0.3.0", path = "../ext/cache" }
|
||||
deno_console = { version = "0.71.0", path = "../ext/console" }
|
||||
deno_core = { version = "0.153.0", path = "../core" }
|
||||
deno_crypto = { version = "0.85.0", path = "../ext/crypto" }
|
||||
|
@ -49,7 +49,7 @@ winapi = "0.3.9"
|
|||
|
||||
[dependencies]
|
||||
deno_broadcast_channel = { version = "0.65.0", path = "../ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.2.0", path = "../ext/cache" }
|
||||
deno_cache = { version = "0.3.0", path = "../ext/cache" }
|
||||
deno_console = { version = "0.71.0", path = "../ext/console" }
|
||||
deno_core = { version = "0.153.0", path = "../core" }
|
||||
deno_crypto = { version = "0.85.0", path = "../ext/crypto" }
|
||||
|
|
Loading…
Reference in a new issue