- main
- manifest
- deps
- main
- Install
- Run
use fastly::{Error, Request};
use lazy_static::lazy_static;
use regex::Regex;
use serde_json::Value;
use std::io::Write;
lazy_static! {
static ref DATA_REGEX: Regex = Regex::new(r"^([^:]+?)\s*:\s*(.*?)\s*$").unwrap();
}
const ALLOW_CITY_LIST: [&str; 10] = [
"Atlanta",
"Berlin",
"Dublin",
"Boston",
"Denver",
"Tokyo",
"Singapore",
"Los Angeles",
"Dubai",
"San Francisco",
];
const DELIMITER: &str = "\n\n";
const CHUNK_SIZE: usize = 1024;
fn main() -> Result<(), Error> {
let req = Request::from_client();
let mut backend_resp = req.send("origin_0")?;
let mut backend_resp_body = backend_resp.take_body();
let mut client_body = backend_resp.stream_to_client();
let mut buffer = String::new();
for chunk in backend_resp_body.read_chunks(CHUNK_SIZE) {
let Ok(chunk) = chunk else {
break;
};
let mut events_stream = String::from_utf8_lossy(&chunk);
if !buffer.is_empty() {
events_stream = format!("{}{}", &buffer, &events_stream).into();
}
let mut events: Vec<&str> = events_stream.split(DELIMITER).collect();
buffer = events.pop().unwrap_or_default().to_string();
for event in events {
if let Some(city) = get_event_city(event) {
let allow = ALLOW_CITY_LIST.contains(&city.as_str());
println!("City: {city}, include: {allow}");
if !allow {
continue;
}
}
client_body.write_str(event);
client_body.write_str(DELIMITER);
client_body.flush().ok();
}
}
client_body.finish().ok();
Ok(())
}
fn get_event_city(event: &str) -> Option<String> {
event.split('\n').find_map(|line| {
let cap = DATA_REGEX.captures(line)?;
let key = cap.get(1)?.as_str();
if key != "data" {
return None;
}
let value = cap.get(2)?.as_str();
let json_v = serde_json::from_str::<Value>(value).ok()?;
Some(json_v["destination"].as_str()?.to_string())
})
}