-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b8a76f2
commit c3de307
Showing
16 changed files
with
234 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
[server] | ||
address = "0.0.0.0" | ||
port = 8000 | ||
use_proxy = true | ||
|
||
[logging] | ||
log_level = "info" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
[server] | ||
address = "0.0.0.0" | ||
port = 8000 | ||
use_proxy = false | ||
|
||
[logging] | ||
log_level = "info" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,139 @@ | ||
use axum::Json; | ||
use reqwest::Error; | ||
use tracing::{trace, warn}; | ||
use rand::seq::SliceRandom; | ||
use reqwest::{Client, Error, Proxy, StatusCode}; | ||
use serde_json::Value; | ||
use std::time::Duration; | ||
use tracing::{error, trace, warn}; | ||
|
||
const IP_API_ENDPOINT: &str = "http://ip-api.com/json/"; | ||
const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"; | ||
const MAX_RETRIES: usize = 5; // Maximum number of retries if the request fails | ||
|
||
pub async fn get_geolocation(info: &String) -> Result<Json<serde_json::Value>, Error> { | ||
let client = reqwest::Client::new() | ||
.get(format!("{}{}", IP_API_ENDPOINT, info)) | ||
.header("User-Agent", USER_AGENT); | ||
const USER_AGENTS: &[&str] = &[ | ||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3", | ||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0", | ||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15", | ||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36", | ||
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1", | ||
]; | ||
|
||
let response = client.send().await?; | ||
const PROXIES: &[&str] = &[ | ||
"http://34.81.160.132:80", // Taiwan | ||
"http://34.87.84.105:80", // Singapore | ||
"http://117.54.114.102:80", // Indonesia | ||
"http://47.178.24.220:80", // United States | ||
"http://160.86.242.23:8080", // Japan | ||
"http://20.26.249.29:8080", // United Kingdom | ||
"http://198.49.68.80:80", // United States | ||
"http://154.64.226.138:80", // Japan | ||
"http://89.213.0.29:80", // Hong Kong | ||
"http://51.222.161.115:80", // Canada | ||
"http://195.181.172.220:8080", // Netherlands | ||
"http://41.169.69.91:3128", // South Africa | ||
"http://85.215.64.49:80", // Germany | ||
"http://162.223.90.130:80", // United States | ||
"http://23.247.136.245:80", // Singapore | ||
"http://133.18.234.13:80", // Japan | ||
"http://41.204.53.19:80", // Ghana | ||
"http://41.204.53.30:80", // Ghana | ||
]; | ||
|
||
if response.status().is_success() { | ||
trace!( | ||
"Request to external db successfully with status code: {}", | ||
response.status() | ||
); | ||
// Function to get a random User-Agent | ||
fn get_random_user_agent() -> &'static str { | ||
USER_AGENTS.choose(&mut rand::thread_rng()).unwrap() | ||
} | ||
|
||
// Function to configure the reqwest client, optionally using a proxy | ||
fn configure_client(use_proxy: bool) -> Result<Client, Error> { | ||
let mut client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10)); // Set timeout of 10 seconds | ||
|
||
if use_proxy { | ||
// Randomly select a proxy from the list | ||
let proxy_url = PROXIES.choose(&mut rand::thread_rng()).unwrap(); | ||
let proxy = Proxy::all(*proxy_url)?; | ||
client_builder = client_builder.proxy(proxy); | ||
|
||
trace!("Proxy enabled: using proxy {}", proxy_url); | ||
} else { | ||
warn!( | ||
"Request to external geolocation db failed with status code: {}", | ||
response.status() | ||
); | ||
trace!("Proxy disabled: connecting directly"); | ||
} | ||
|
||
let response_json: serde_json::Value = response.json().await?; | ||
client_builder.build() | ||
} | ||
|
||
// Main function to perform the request, retrying if the request fails | ||
pub async fn get_geolocation(info: &String, use_proxy: bool) -> Result<Json<Value>, Error> { | ||
// Log info about proxy status | ||
if use_proxy { | ||
trace!("using proxy to get geolocation data"); | ||
} else { | ||
trace!("getting geolocation data without proxy"); | ||
} | ||
|
||
let mut attempts = 0; // Number of attempts | ||
|
||
while attempts < MAX_RETRIES { | ||
attempts += 1; | ||
|
||
// Get random User-Agent | ||
let user_agent = get_random_user_agent(); | ||
|
||
// Configure the client with or without proxy | ||
let client = match configure_client(use_proxy) { | ||
Ok(c) => c, | ||
Err(e) => { | ||
warn!("Error configuring client: {:?}", e); | ||
continue; // If client configuration fails, retry | ||
} | ||
}; | ||
|
||
// Log the User-Agent being used | ||
trace!( | ||
"Attempting request using User-Agent: '{}' (Attempt {}/{})", | ||
user_agent, | ||
attempts, | ||
MAX_RETRIES | ||
); | ||
|
||
// Make the request | ||
let response = client | ||
.get(format!("{}{}", IP_API_ENDPOINT, info)) | ||
.header("User-Agent", user_agent) | ||
.send() | ||
.await; | ||
|
||
match response { | ||
Ok(resp) => { | ||
// If the request is successful | ||
if resp.status().is_success() { | ||
trace!("Request succeeded with status: {}", resp.status()); | ||
let response_json: Value = resp.json().await?; | ||
return Ok(Json(response_json)); | ||
} else { | ||
warn!( | ||
"Request failed with status: {} (Attempt {}/{})", | ||
resp.status(), | ||
attempts, | ||
MAX_RETRIES | ||
); | ||
// If status code indicates too many requests, wait before retrying | ||
if resp.status() == StatusCode::TOO_MANY_REQUESTS { | ||
warn!("Too many requests, retrying after a delay..."); | ||
tokio::time::sleep(Duration::from_secs(2)).await; | ||
} | ||
} | ||
} | ||
Err(e) => { | ||
error!( | ||
"Request error: {:?} (Attempt {}/{})", | ||
e, attempts, MAX_RETRIES | ||
); | ||
// If a connection error occurs, retry | ||
} | ||
} | ||
} | ||
|
||
Ok(Json(response_json)) | ||
// Return a simple JSON error message after max retries | ||
Ok(Json(serde_json::json!({ | ||
"error": "Max retries reached" | ||
}))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.