From eacd6a7f295a9a8ce4f4ca38cbf3e9905c4a5d02 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Mon, 3 Oct 2022 10:52:54 +0530 Subject: [PATCH] chore(ext/cache): make helper functions public (#16117) --- Cargo.lock | 2 +- cli/Cargo.toml | 2 +- ext/cache/Cargo.toml | 2 +- ext/cache/lib.rs | 199 +++++++++++++++++++++++++++++++++++++------ ext/cache/sqlite.rs | 87 +------------------ runtime/Cargo.toml | 4 +- 6 files changed, 183 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9a4d070ae..c125f02a82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "deno_cache" -version = "0.2.0" +version = "0.3.0" dependencies = [ "async-trait", "deno_core", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 0161eed417..12b605aa91 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -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" } diff --git a/ext/cache/Cargo.toml b/ext/cache/Cargo.toml index 38e08356d8..ea824de463 100644 --- a/ext/cache/Cargo.toml +++ b/ext/cache/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_cache" -version = "0.2.0" +version = "0.3.0" authors = ["the Deno authors"] edition = "2021" license = "MIT" diff --git a/ext/cache/lib.rs b/ext/cache/lib.rs index 350efbc389..e6fdaa7642 100644 --- a/ext/cache/lib.rs +++ b/ext/cache/lib.rs @@ -20,6 +20,38 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; +#[derive(Clone)] +pub struct CreateCache(pub Arc C>); + +pub fn init( + maybe_create_cache: Option>, +) -> Extension { + Extension::builder() + .js(include_js_files!( + prefix "deno:ext/cache", + "01_cache.js", + )) + .ops(vec![ + op_cache_storage_open::decl::(), + op_cache_storage_has::decl::(), + op_cache_storage_delete::decl::(), + op_cache_put::decl::(), + op_cache_match::decl::(), + op_cache_delete::decl::(), + ]) + .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(pub Arc 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( - maybe_create_cache: Option>, -) -> Extension { - Extension::builder() - .js(include_js_files!( - prefix "deno:ext/cache", - "01_cache.js", - )) - .ops(vec![ - op_cache_storage_open::decl::(), - op_cache_storage_has::decl::(), - op_cache_storage_delete::decl::(), - op_cache_put::decl::(), - op_cache_match::decl::(), - op_cache_delete::decl::(), - ]) - .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 { + 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 { + 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 { + 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 } diff --git a/ext/cache/sqlite.rs b/ext/cache/sqlite.rs index 1e55918395..7e97fb5633 100644 --- a/ext/cache/sqlite.rs +++ b/ext/cache/sqlite.rs @@ -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 { - vary_header - .split(',') - .map(|s| s.trim().to_lowercase()) - .collect() -} - -fn get_header( - name: &str, - headers: &[(ByteString, ByteString)], -) -> Option { - 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 { "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 { - 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 -} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index e31893bb72..467623933a 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -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" }