diff --git a/pingora-cache/src/lib.rs b/pingora-cache/src/lib.rs index bc370b7f..0464297d 100644 --- a/pingora-cache/src/lib.rs +++ b/pingora-cache/src/lib.rs @@ -46,6 +46,7 @@ use crate::max_file_size::MaxFileSizeMissHandler; pub use key::CacheKey; use lock::{CacheLock, LockStatus, Locked}; pub use memory::MemCache; +pub use meta::{set_compression_dict_content, set_compression_dict_path}; pub use meta::{CacheMeta, CacheMetaDefaults}; pub use storage::{HitHandler, MissHandler, PurgeType, Storage}; pub use variance::VarianceBuilder; @@ -1237,12 +1238,3 @@ impl HttpCache { .set_tag(|| Tag::new("is_subrequest", true)) } } - -/// Set the header compression dictionary, which helps serialize http header. -/// -/// Return false if it is already set. -pub fn set_compression_dict_path(path: &str) -> bool { - crate::meta::COMPRESSION_DICT_PATH - .set(path.to_string()) - .is_ok() -} diff --git a/pingora-cache/src/meta.rs b/pingora-cache/src/meta.rs index fd608d4e..75a1a0dd 100644 --- a/pingora-cache/src/meta.rs +++ b/pingora-cache/src/meta.rs @@ -15,9 +15,13 @@ //! Metadata for caching pub use http::Extensions; +use log::warn; +use once_cell::sync::{Lazy, OnceCell}; use pingora_error::{Error, ErrorType::*, OrErr, Result}; +use pingora_header_serde::HeaderSerde; use pingora_http::{HMap, ResponseHeader}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; use std::time::{Duration, SystemTime}; use crate::key::HashBinary; @@ -561,53 +565,20 @@ impl CacheMetaDefaults { } } -use log::warn; -use once_cell::sync::{Lazy, OnceCell}; -use pingora_header_serde::HeaderSerde; -use std::fs::File; -use std::io::Read; - -/* load header compression engine and its dictionary globally */ -pub(crate) static COMPRESSION_DICT_PATH: OnceCell = OnceCell::new(); - -fn load_file(path: &String) -> Option> { - let mut file = File::open(path) - .map_err(|e| { - warn!( - "failed to open header compress dictionary file at {}, {:?}", - path, e - ); - e - }) - .ok()?; - let mut dict = Vec::new(); - file.read_to_end(&mut dict) - .map_err(|e| { - warn!( - "failed to read header compress dictionary file at {}, {:?}", - path, e - ); - e - }) - .ok()?; - - Some(dict) -} +/// The dictionary content for header compression. +/// +/// Used during initialization of [`HEADER_SERDE`]. +static COMPRESSION_DICT_CONTENT: OnceCell> = OnceCell::new(); static HEADER_SERDE: Lazy = Lazy::new(|| { - let dict_path_opt = COMPRESSION_DICT_PATH.get(); - - if dict_path_opt.is_none() { - warn!("COMPRESSION_DICT_PATH is not set"); - } - - let result = dict_path_opt.and_then(load_file); - - if result.is_none() { - warn!("HeaderSerde not loaded from file"); - } - - HeaderSerde::new(result) + let dict_opt = if let Some(dict_content) = COMPRESSION_DICT_CONTENT.get() { + Some(dict_content.to_vec()) + } else { + warn!("no header compression dictionary loaded - use set_compression_dict_content() or set_compression_dict_path() to set one"); + None + }; + + HeaderSerde::new(dict_opt) }); pub(crate) fn header_serialize(header: &ResponseHeader) -> Result> { @@ -617,3 +588,31 @@ pub(crate) fn header_serialize(header: &ResponseHeader) -> Result> { pub(crate) fn header_deserialize>(buf: T) -> Result { HEADER_SERDE.deserialize(buf.as_ref()) } + +/// Load the header compression dictionary from a file, which helps serialize http header. +/// +/// Returns false if it is already set or if the file could not be read. +/// +/// Use [`set_compression_dict_content`] to set the dictionary from memory instead. +pub fn set_compression_dict_path(path: &str) -> bool { + match std::fs::read(path) { + Ok(dict) => COMPRESSION_DICT_CONTENT.set(dict.into()).is_ok(), + Err(e) => { + warn!( + "failed to read header compress dictionary file at {}, {:?}", + path, e + ); + false + } + } +} + +/// Set the header compression dictionary content, which helps serialize http header. +/// +/// Returns false if it is already set. +/// +/// This is an alernative to [`set_compression_dict_path`], allowing use of +/// a dictionary without an external file. +pub fn set_compression_dict_content(content: Cow<'static, [u8]>) -> bool { + COMPRESSION_DICT_CONTENT.set(content).is_ok() +}