Making periodic http requests in Rust

Making http requests in Rust using reqwest, tokio, async/await and http proxies and cookies

In this post, we will look into how we can write. a a simple program to make periodic http requests using request in Rust.

Lets start with creating a client using request

let client = reqwest::Client::builder()

Now, lets add basic http headers and some cookies, to the client,

let user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36";
let cookies = format!("{}", std::env::var("COOKIES")?);

let mut headers = header::HeaderMap::new();
headers.insert("accept", header::HeaderValue::from_static("*/*"));
headers.insert("cookie", header::HeaderValue::from_str(&cookies).unwrap());
    
    
let client = reqwest::Client::builder()
    .user_agent(user_agent)
    .default_headers(headers)

And then add our http proxy to the client with:

let proxy_url = format!("{}", std::env::var("PROXY_URL")?);

let http_proxy = reqwest::Proxy::http(&proxy_url)?;
let https_proxy = reqwest::Proxy::https(&proxy_url)?;


let client = reqwest::Client::builder()
        .user_agent(user_agent)
        .default_headers(headers)
        .danger_accept_invalid_certs(true)
        .gzip(true)
        .proxy(http_proxy)
        .proxy(https_proxy)
        .connect_timeout(std::time::Duration::from_secs(60))
        .timeout(std::time::Duration::from_secs(600))
        .build()
        .unwrap();

Now let's wrap everything together with

use dotenv::dotenv;
use reqwest::header;
use reqwest::Client;
use tokio::time;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenv().ok();

    let proxy_url = format!("{}", std::env::var("PROXY_URL")?);
    let cookies = format!("{}", std::env::var("COOKIES")?);
    let ipify_url = format!("https://api.ipify.org?format=json");

    let user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36";
    let http_proxy = reqwest::Proxy::http(&proxy_url)?;
    let https_proxy = reqwest::Proxy::https(&proxy_url)?;

    let mut headers = header::HeaderMap::new();
    headers.insert("accept", header::HeaderValue::from_static("*/*"));
    headers.insert("cookie", header::HeaderValue::from_str(&cookies).unwrap());

    let client = reqwest::Client::builder()
        .user_agent(user_agent)
        .default_headers(headers)
        .danger_accept_invalid_certs(true)
        .gzip(true)
        .proxy(http_proxy)
        .proxy(https_proxy)
        .connect_timeout(std::time::Duration::from_secs(60))
        .timeout(std::time::Duration::from_secs(600))
        .build()
        .unwrap();

    tokio::join!(fetch(&client, &ipify_url), fetch(&client, &ipify_url));

    Ok(())
}

async fn fetch(client: &Client, url: &str) -> Result<(), Box<dyn std::error::Error>> {
    let mut interval = time::interval(std::time::Duration::from_secs(60));

    loop {
        interval.tick().await;

        let res = client.get(url).send().await.unwrap();
        match res.status() {
            reqwest::StatusCode::OK => {
                println!("Status: OK, url:{:?}", res.url().path());
                println!("URL: {}", url);

            }
            status => println!("status: {}, path: {}", status, res.url().path()),
        }
    }
}