/
githubmirror
/
servo
Обзор
Документация
Войти
/
githubmirror
/
servo
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
components/net/fetch/cors_cache.rs
192 строки
6 KB
Simon Wülker
Update rustfmt to the 2024 style edition (#35764)
03 мар 2025, 14:26
Не верифицирован
03 мар 2025, 14:26
3d320fa
Код
Авторство
О чём код?
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! An implementation of the [CORS preflight cache](https://fetch.spec.whatwg.org/#cors-preflight-cache) //! For now this library is XHR-specific. //! For stuff involving `<img>`, `<iframe>`, `<form>`, etc please check what //! the request mode should be and compare with the fetch spec //! This library will eventually become the core of the Fetch crate //! with CORSRequest being expanded into FetchRequest (etc) use std::time::{Duration, Instant}; use http::Method; use http::header::HeaderName; use net_traits::request::{CredentialsMode, Origin, Request}; use servo_url::ServoUrl; /// Union type for CORS cache entries /// /// Each entry might pertain to a header or method #[derive(Clone, Debug)] pub enum HeaderOrMethod { HeaderData(HeaderName), MethodData(Method), } impl HeaderOrMethod { fn match_header(&self, header_name: &HeaderName) -> bool { match *self { HeaderOrMethod::HeaderData(ref n) => n == header_name, _ => false, } } fn match_method(&self, method: &Method) -> bool { match *self { HeaderOrMethod::MethodData(ref m) => m == method, _ => false, } } } /// An entry in the CORS cache #[derive(Clone, Debug)] pub struct CorsCacheEntry { pub origin: Origin, pub url: ServoUrl, pub max_age: Duration, pub credentials: bool, pub header_or_method: HeaderOrMethod, created: Instant, } impl CorsCacheEntry { fn new( origin: Origin, url: ServoUrl, max_age: Duration, credentials: bool, header_or_method: HeaderOrMethod, ) -> CorsCacheEntry { CorsCacheEntry { origin, url, max_age, credentials, header_or_method, created: Instant::now(), } } } fn match_headers(cors_cache: &CorsCacheEntry, cors_req: &Request) -> bool { cors_cache.origin == cors_req.origin && cors_cache.url == cors_req.current_url() && (cors_cache.credentials || cors_req.credentials_mode != CredentialsMode::Include) } /// A simple, vector-based CORS Cache #[derive(Clone, Default)] pub struct CorsCache(Vec<CorsCacheEntry>); impl CorsCache { fn find_entry_by_header<'a>( &'a mut self, request: &Request, header_name: &HeaderName, ) -> Option<&'a mut CorsCacheEntry> { self.cleanup(); self.0 .iter_mut() .find(|e| match_headers(e, request) && e.header_or_method.match_header(header_name)) } fn find_entry_by_method<'a>( &'a mut self, request: &Request, method: Method, ) -> Option<&'a mut CorsCacheEntry> { // we can take the method from CorSRequest itself self.cleanup(); self.0 .iter_mut() .find(|e| match_headers(e, request) && e.header_or_method.match_method(&method)) } /// Remove old entries pub fn cleanup(&mut self) { let CorsCache(buf) = self.clone(); let now = Instant::now(); let new_buf: Vec<CorsCacheEntry> = buf .into_iter() .filter(|e| now < e.created + e.max_age) .collect(); *self = CorsCache(new_buf); } /// Returns true if an entry with a /// [matching header](https://fetch.spec.whatwg.org/#concept-cache-match-header) is found pub fn match_header(&mut self, request: &Request, header_name: &HeaderName) -> bool { self.find_entry_by_header(request, header_name).is_some() } /// Updates max age if an entry for a /// [matching header](https://fetch.spec.whatwg.org/#concept-cache-match-header) is found. /// /// If not, it will insert an equivalent entry pub fn match_header_and_update( &mut self, request: &Request, header_name: &HeaderName, new_max_age: Duration, ) -> bool { match self .find_entry_by_header(request, header_name) .map(|e| e.max_age = new_max_age) { Some(_) => true, None => { self.insert(CorsCacheEntry::new( request.origin.clone(), request.current_url(), new_max_age, request.credentials_mode == CredentialsMode::Include, HeaderOrMethod::HeaderData(header_name.clone()), )); false }, } } /// Returns true if an entry with a /// [matching method](https://fetch.spec.whatwg.org/#concept-cache-match-method) is found pub fn match_method(&mut self, request: &Request, method: Method) -> bool { self.find_entry_by_method(request, method).is_some() } /// Updates max age if an entry for /// [a matching method](https://fetch.spec.whatwg.org/#concept-cache-match-method) is found. /// /// If not, it will insert an equivalent entry pub fn match_method_and_update( &mut self, request: &Request, method: Method, new_max_age: Duration, ) -> bool { match self .find_entry_by_method(request, method.clone()) .map(|e| e.max_age = new_max_age) { Some(_) => true, None => { self.insert(CorsCacheEntry::new( request.origin.clone(), request.current_url(), new_max_age, request.credentials_mode == CredentialsMode::Include, HeaderOrMethod::MethodData(method), )); false }, } } /// Insert an entry pub fn insert(&mut self, entry: CorsCacheEntry) { self.cleanup(); self.0.push(entry); } }