1
0
Fork 0
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:
Satya Rohith 2022-10-03 10:52:54 +05:30 committed by GitHub
parent e2990be264
commit eacd6a7f29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 183 additions and 113 deletions

2
Cargo.lock generated
View file

@ -943,7 +943,7 @@ dependencies = [
[[package]]
name = "deno_cache"
version = "0.2.0"
version = "0.3.0"
dependencies = [
"async-trait",
"deno_core",

View file

@ -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" }

View file

@ -2,7 +2,7 @@
[package]
name = "deno_cache"
version = "0.2.0"
version = "0.3.0"
authors = ["the Deno authors"]
edition = "2021"
license = "MIT"

203
ext/cache/lib.rs vendored
View file

@ -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>);
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);
/// 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;
}
Ok(())
})
.build()
}
true
}
pub fn get_declaration() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_cache.d.ts")
#[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
}
})
.map(|(_, v)| v.to_owned())
}
#[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
View file

@ -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
}

View file

@ -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" }