1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
use aw_models::Event;
use serde_json::value::Value;

/// Adds $protocol, $domain, $path and $params keys for events with an "url" key
///
/// But it only adds the generated field if it exists, for example if a url does not have a path
/// the path value will not be set at all.
///
/// # Example
/// ```ignore
/// input:  {
///           "data": {
///             "url": "http://google.com/test"
///           }
///         }
/// output: {
///           "data": {
///             "$domain": "google.com",
///             "$path": "/test",
///             "$protocol": "http"
///           }
///         }
/// ```
pub fn split_url_event(event: &mut Event) {
    use rocket::http::uri::Absolute;
    let uri_str = match event.data.get("url") {
        None => return,
        Some(val) => match val {
            Value::String(s) => s.clone(),
            _ => return,
        },
    };
    let uri = match Absolute::parse(&uri_str) {
        Ok(uri) => uri,
        Err(_) => return,
    };
    // Protocol
    let protocol = uri.scheme().to_string();
    event
        .data
        .insert("$protocol".to_string(), Value::String(protocol));
    // Domain
    let domain = match uri.authority() {
        Some(authority) => authority.host().trim_start_matches("www.").to_string(),
        None => "".to_string(),
    };
    event
        .data
        .insert("$domain".to_string(), Value::String(domain));
    // Path
    let path = match uri.origin() {
        Some(origin) => origin.path().to_string(),
        None => "".to_string(),
    };
    event.data.insert("$path".to_string(), Value::String(path));
    // Params
    // TODO: What's the difference between params and query?
    let params = match uri.origin() {
        Some(origin) => match origin.query() {
            Some(query) => query.to_string(),
            None => "".to_string(),
        },
        None => "".to_string(),
    };
    event
        .data
        .insert("$params".to_string(), Value::String(params));

    // TODO: aw-server-python also has options and identifier
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use chrono::DateTime;
    use chrono::Duration;
    use serde_json::json;

    use aw_models::Event;

    use super::split_url_event;

    #[test]
    fn test_split_url_events() {
        let mut e1 = Event {
            id: None,
            timestamp: DateTime::from_str("2000-01-01T00:00:01Z").unwrap(),
            duration: Duration::seconds(1),
            data: json_map! {"url": "http://www.google.com/path?query=1"},
        };
        split_url_event(&mut e1);
        assert_eq!(
            e1.data,
            json_map! {
                "url": json!("http://www.google.com/path?query=1"),
                "$protocol": json!("http"),
                "$domain": json!("google.com"),
                "$path": json!("/path"),
                "$params": json!("query=1")
            }
        );
    }
}