Skip to content

Instantly share code, notes, and snippets.

@OliverBrotchie
Last active October 12, 2021 20:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OliverBrotchie/c41689394d8b1894a804255c14d7ef8d to your computer and use it in GitHub Desktop.
Save OliverBrotchie/c41689394d8b1894a804255c14d7ef8d to your computer and use it in GitHub Desktop.
Async connection handler
use actix_web::http::header::HeaderMap;
use chrono::{DateTime, Utc};
use std::collections::HashMap;
use std::sync::Mutex;
#[derive(Debug, Clone)]
pub struct Fingerprint {
properties: Vec<(String, String)>,
fonts: Vec<String>,
headers: HeaderMap,
timestamp: DateTime<Utc>,
}
#[derive(Clone)]
pub struct ConnectionHandler<T: FnMut(String, &Fingerprint)> {
data: HashMap<String, Fingerprint>,
return_fn: T,
}
impl<T> ConnectionHandler<T>
where
T: FnMut(String, &Fingerprint),
{
pub fn insert(&mut self, ip: String, key: String, value: String, headers: Option<&HeaderMap>) {
match self.data.get_mut(&ip) {
Some(f) => {
if key == "font-name" {
f.fonts.push(value)
} else {
f.properties.push((key, value))
}
}
None => {
self.data.insert(
ip.clone(),
Fingerprint {
properties: Vec::new(),
fonts: Vec::new(),
headers: headers.unwrap().clone(),
timestamp: chrono::offset::Utc::now(),
},
);
self.insert(ip, key, value, None);
// Wait x seconds before calling this!
(self.return_fn)(ip, self.data.get(&ip).unwrap());
}
}
}
}
use actix_web::{get, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
use std::collections::HashMap;
use std::sync::Mutex;
mod handler;
#[get("/some/url/{key}={value}")]
async fn new_prop<T: FnMut(String, &handler::Fingerprint)>(
con_handler: web::Data<handler::ConnectionHandler<T>>,
request: HttpRequest,
web::Path((key, value)): web::Path<(String, String)>,
) -> impl Responder {
// Just an example (will not work due to threading issues)
con_handler.insert(
request
.connection_info()
.realip_remote_addr()
.unwrap()
.to_owned(),
key,
value,
Some(request.headers()),
);
HttpResponse::Gone()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
const PORT: u16 = 8000;
println!("🚀 Server running on port: {}!", PORT);
// Define the connection handler
let h = web::Data::new(handler::ConnectionHandler {
data: HashMap::new(),
return_fn: |ip: String, fingerprint: &handler::Fingerprint| {
println!("IP: {}, Fingerprint: {:#?}", ip, fingerprint)
},
});
HttpServer::new(|| {
App::new()
.app_data(h.clone())
.service(new_prop)
})
.bind(format!("127.0.0.1:{}", PORT))?
.run()
.await
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment