mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-11-04 09:34:04 +00:00 
			
		
		
		
	Start to implement requests limit
This commit is contained in:
		
							
								
								
									
										36
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -293,6 +293,15 @@ dependencies = [
 | 
				
			|||||||
 "const-random",
 | 
					 "const-random",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "ahash"
 | 
				
			||||||
 | 
					version = "0.3.8"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "const-random",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "aho-corasick"
 | 
					name = "aho-corasick"
 | 
				
			||||||
version = "0.7.10"
 | 
					version = "0.7.10"
 | 
				
			||||||
@@ -509,9 +518,9 @@ checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "cfg-if"
 | 
					name = "cfg-if"
 | 
				
			||||||
version = "0.1.9"
 | 
					version = "0.1.10"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
 | 
					checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "chrono"
 | 
					name = "chrono"
 | 
				
			||||||
@@ -549,6 +558,7 @@ dependencies = [
 | 
				
			|||||||
 "actix-web",
 | 
					 "actix-web",
 | 
				
			||||||
 "bytes",
 | 
					 "bytes",
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
 | 
					 "dashmap",
 | 
				
			||||||
 "encoding_rs",
 | 
					 "encoding_rs",
 | 
				
			||||||
 "futures",
 | 
					 "futures",
 | 
				
			||||||
 "image",
 | 
					 "image",
 | 
				
			||||||
@@ -666,6 +676,17 @@ dependencies = [
 | 
				
			|||||||
 "lazy_static",
 | 
					 "lazy_static",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "dashmap"
 | 
				
			||||||
 | 
					version = "3.11.10"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "ahash 0.3.8",
 | 
				
			||||||
 | 
					 "cfg-if",
 | 
				
			||||||
 | 
					 "num_cpus",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "deflate"
 | 
					name = "deflate"
 | 
				
			||||||
version = "0.8.4"
 | 
					version = "0.8.4"
 | 
				
			||||||
@@ -1075,7 +1096,7 @@ version = "0.6.3"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead"
 | 
					checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "ahash",
 | 
					 "ahash 0.2.18",
 | 
				
			||||||
 "autocfg 0.1.7",
 | 
					 "autocfg 0.1.7",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1271,9 +1292,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "lexical"
 | 
					name = "lexical"
 | 
				
			||||||
version = "4.2.0"
 | 
					version = "4.0.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "eaad0ee8120fc0cf7df7e8fdbe79bf9d6189351404feb88f4e4a4bb5307bc594"
 | 
					checksum = "0afaeae1c07c575338ef6809875bfea8daa9ea8b2ee381ef1f93ba0c6e32f003"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if",
 | 
					 "cfg-if",
 | 
				
			||||||
 "lexical-core",
 | 
					 "lexical-core",
 | 
				
			||||||
@@ -1282,12 +1303,11 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "lexical-core"
 | 
					name = "lexical-core"
 | 
				
			||||||
version = "0.6.7"
 | 
					version = "0.6.2"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "f86d66d380c9c5a685aaac7a11818bdfa1f733198dfd9ec09c70b762cd12ad6f"
 | 
					checksum = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "arrayvec",
 | 
					 "arrayvec",
 | 
				
			||||||
 "bitflags",
 | 
					 | 
				
			||||||
 "cfg-if",
 | 
					 "cfg-if",
 | 
				
			||||||
 "rustc_version",
 | 
					 "rustc_version",
 | 
				
			||||||
 "ryu",
 | 
					 "ryu",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,3 +28,4 @@ lazy_static = "1.4.0"
 | 
				
			|||||||
mime_guess = "2.0.3"
 | 
					mime_guess = "2.0.3"
 | 
				
			||||||
pdf = "0.6.3"
 | 
					pdf = "0.6.3"
 | 
				
			||||||
regex = "1.4.2"
 | 
					regex = "1.4.2"
 | 
				
			||||||
 | 
					dashmap = "3.11.10"
 | 
				
			||||||
@@ -57,6 +57,9 @@ pub mod database_tables_names {
 | 
				
			|||||||
    pub const NOTIFICATIONS_TABLE: &str = "comunic_notifications";
 | 
					    pub const NOTIFICATIONS_TABLE: &str = "comunic_notifications";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Lifetime of limit counter (1 hour)
 | 
				
			||||||
 | 
					pub const LIMIT_COUNTER_LIFETIME: u64 = 60 * 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// The account image to show for user who do not have any
 | 
					/// The account image to show for user who do not have any
 | 
				
			||||||
pub const DEFAULT_ACCOUNT_IMAGE: &str = "avatars/0Reverse.png";
 | 
					pub const DEFAULT_ACCOUNT_IMAGE: &str = "avatars/0Reverse.png";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ use crate::controllers::routes::{get_routes, RequestResult, Route};
 | 
				
			|||||||
use crate::controllers::routes::Method::{GET, POST};
 | 
					use crate::controllers::routes::Method::{GET, POST};
 | 
				
			||||||
use crate::data::config::Config;
 | 
					use crate::data::config::Config;
 | 
				
			||||||
use crate::data::http_request_handler::{HttpRequestHandler, PostFile, RequestValue};
 | 
					use crate::data::http_request_handler::{HttpRequestHandler, PostFile, RequestValue};
 | 
				
			||||||
 | 
					use crate::helpers::requests_limit_helper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Main server functions
 | 
					/// Main server functions
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@@ -237,6 +238,9 @@ async fn process_request(custom_req: CustomRequest) -> HttpResponse {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    let route = route.unwrap();
 | 
					    let route = route.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Clean requests limit
 | 
				
			||||||
 | 
					    requests_limit_helper::clean_cache().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Execute the request
 | 
					    // Execute the request
 | 
				
			||||||
    let mut request = HttpRequestHandler::new(custom_req.req, custom_req.body);
 | 
					    let mut request = HttpRequestHandler::new(custom_req.req, custom_req.body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -280,6 +284,10 @@ async fn process_request(custom_req: CustomRequest) -> HttpResponse {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Given the configuration, start the server
 | 
					/// Given the configuration, start the server
 | 
				
			||||||
pub async fn start_server(conf: &Config) -> std::io::Result<()> {
 | 
					pub async fn start_server(conf: &Config) -> std::io::Result<()> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize limit helper
 | 
				
			||||||
 | 
					    requests_limit_helper::init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let addr = conf.server_listen_address();
 | 
					    let addr = conf.server_listen_address();
 | 
				
			||||||
    println!("Start to listen on http://{}/", addr);
 | 
					    println!("Start to listen on http://{}/", addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,3 +16,4 @@ pub mod survey_helper;
 | 
				
			|||||||
pub mod comments_helper;
 | 
					pub mod comments_helper;
 | 
				
			||||||
pub mod notifications_helper;
 | 
					pub mod notifications_helper;
 | 
				
			||||||
pub mod webapp_helper;
 | 
					pub mod webapp_helper;
 | 
				
			||||||
 | 
					pub mod requests_limit_helper;
 | 
				
			||||||
							
								
								
									
										60
									
								
								src/helpers/requests_limit_helper.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/helpers/requests_limit_helper.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					//! # Requests limit helper
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Handle the limitation of requests, depending on threshold criterias
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::sync::{Arc, Mutex};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::constants::LIMIT_COUNTER_LIFETIME;
 | 
				
			||||||
 | 
					use crate::data::error::ResultBoxError;
 | 
				
			||||||
 | 
					use crate::utils::date_utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Information about a IP address limitation
 | 
				
			||||||
 | 
					struct IpInfo {
 | 
				
			||||||
 | 
					    time_start: u64,
 | 
				
			||||||
 | 
					    count: u64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Limits cache
 | 
				
			||||||
 | 
					type Cache = Arc<dashmap::DashMap<String, IpInfo>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static mut LIMITS_CACHE: Option<Arc<Mutex<Cache>>> = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Initialize limit cache storage
 | 
				
			||||||
 | 
					pub fn init() {
 | 
				
			||||||
 | 
					    let limits_cache = Arc::new(dashmap::DashMap::new());
 | 
				
			||||||
 | 
					    let limits_cache = Some(Arc::new(Mutex::new(limits_cache)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsafe {
 | 
				
			||||||
 | 
					        LIMITS_CACHE = limits_cache;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get access to the cache. This resource must absolutely be released as quickly as possible
 | 
				
			||||||
 | 
					fn get_cache() -> ResultBoxError<Cache> {
 | 
				
			||||||
 | 
					    let cache: Cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsafe {
 | 
				
			||||||
 | 
					        let guard = LIMITS_CACHE.as_ref().unwrap().lock();
 | 
				
			||||||
 | 
					        cache = guard.unwrap().clone();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(cache)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Clean cached information
 | 
				
			||||||
 | 
					pub fn clean_cache() -> ResultBoxError {
 | 
				
			||||||
 | 
					    let time = date_utils::time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let cache = get_cache()?;
 | 
				
			||||||
 | 
					    let obsolete_ips: Vec<String> = cache
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .filter(|k| k.time_start + LIMIT_COUNTER_LIFETIME < time)
 | 
				
			||||||
 | 
					        .map(|k| k.key().to_string())
 | 
				
			||||||
 | 
					        .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for obsolete_ip in obsolete_ips {
 | 
				
			||||||
 | 
					        cache.remove(&obsolete_ip);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user