aboutsummaryrefslogtreecommitdiff
path: root/src/get.rs
blob: 95071253e297ee702185e0b56377426afe6b21ca (plain)
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
use std::net::SocketAddr;

use axum::extract::{ConnectInfo, Path};
use axum::http::HeaderMap;
use axum::http::StatusCode;
use axum::response::{Html, IntoResponse, Redirect};
use axum::Extension;

use info_utils::prelude::*;

use crate::ServerState;
use crate::UrlRow;

pub async fn get_index() -> Html<&'static str> {
    Html("hello, world!")
}

pub async fn get_id(
    headers: HeaderMap,
    ConnectInfo(addr): ConnectInfo<SocketAddr>,
    Extension(state): Extension<ServerState>,
    Path(id): Path<String>,
) -> impl IntoResponse {
    let mut show_request = false;
    log!("Request for '{}' from {}", id.clone(), addr.ip());
    let mut use_id = id;
    if use_id.ends_with('+') {
        show_request = true;
        use_id.pop();
    }

    let item = sqlx::query_as!(UrlRow, "SELECT * FROM chela.urls WHERE id = $1", use_id)
        .fetch_one(&state.db_pool)
        .await;
    if let Ok(it) = item {
        if url::Url::parse(&it.url).is_ok() {
            if show_request {
                return Html(format!(
                    "<pre>{}/{} -> <a href={}>{}</a></pre>",
                    state.host, it.id, it.url, it.url
                ))
                .into_response();
            } else {
                log!("Redirecting {} -> {}", it.id, it.url);
                save_analytics(headers, it.clone(), addr, state).await;
                return Redirect::temporary(it.url.as_str()).into_response();
            }
        }
    }

    return (StatusCode::NOT_FOUND, Html("<pre>404</pre>")).into_response();
}

pub async fn save_analytics(
    headers: HeaderMap,
    item: UrlRow,
    addr: SocketAddr,
    state: ServerState,
) {
    let id = item.id;
    let ip = addr.ip().to_string();
    let referer = match headers.get("referer") {
        Some(it) => {
            if let Ok(i) = it.to_str() {
                Some(i)
            } else {
                None
            }
        }
        None => None,
    };
    let user_agent = match headers.get("user-agent") {
        Some(it) => {
            if let Ok(i) = it.to_str() {
                Some(i)
            } else {
                None
            }
        }
        None => None,
    };

    let res = sqlx::query!(
        "
INSERT INTO chela.tracking (id,ip,referrer,user_agent) 
VALUES ($1,$2,$3,$4)
       ",
        id,
        ip,
        referer,
        user_agent
    )
    .execute(&state.db_pool)
    .await;

    if res.is_ok() {
        log!("Saved analytics for '{id}' from {ip}");
    }
}