How to pass cli args value into a function that calls via tokio::spawn in parallel mode

Hi there, I'm writing a CLI tool to use in the security penetration area, my problem is that I don't know how to pass CLI arg to a function that is calling via tokio::async and concurrent mode.
my code is below:
line 23 is where I got the arg value
line 38 is where I attempt to use its value to pass to the target function

Error is:
args does not live long enough

borrowed value does not live long enoughrustc(E0597), 19): borrowed value does not live long enough, 35): argument requires that args is borrowed for 'static, 1): args dropped here while still borrowed

use regex::Regex;
use serde::*;
use std::any::Any;
use std::collections::*;
use std::env;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

#[derive(Serialize, Deserialize)]
struct TimeRecord {
    timeStamp: String,
    url: String,

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = env::args().collect();
    if args.len() == 1 {
        panic!("Pass the domain name in the parameter!");

    let domain = &args[1];

    let base_url = format!("{}/robots.txt&output=json&filter=statuscode:200&fl=timestamp,original&collapse=digest",&domain);
    let resp = reqwest::get(base_url).await?.text().await?;

    let json: Vec<TimeRecord> = serde_json::from_str(&resp).expect("JSON was not well-formatted");
    let mut handles = Vec::new();
    let mut result: HashMap<char, usize> = HashMap::new();

    for obj in json {
        if obj.url == "original" {

        let handle = tokio::spawn(async {
            get_robot_file(domain, obj.timeStamp, obj.url).await;

    for handle in handles {
        let map = handle.await.unwrap();


async fn get_robot_file(
    base_domain: &String,
    timestamp: String,
    url: String,
) -> Result<String, Box<dyn std::error::Error>> {
    let base_url = format!("{}if_/{}", timestamp, url);

    let resp = reqwest::get(base_url).await?.text().await?;

    if resp.is_empty() {
        return Ok(String::from("ok"));

    let items: Vec<&str> = resp.trim().split("\n").collect();

    for item in items {
        if item.to_lowercase().contains("disallow:") || item.to_lowercase().contains("allow:") {
            let sub_item: Vec<&str> = item.split(": ").collect();
            if sub_item.capacity() <= 1 {

            let temp = &sub_item[1]
                .replace("\n", "")
                .replace("*", "")
                .replace("\r", "");

            if !temp.is_empty() {
                let mut result = String::new();
                println!("{:#?}", &result);


Looking at the documentation for tokio::spawn(), you'll find the type bound T: Future + Send + 'static. The 'static part means that the async block inside of it cannot reference any borrowed data. Instead, you must clone domain in order to move it into the block:

        let domain = domain.clone();
        let handle = tokio::spawn(async move {
            get_robot_file(&domain, obj.timeStamp, obj.url).await;

Also, later in the file, you download from the URL{}if_/{}. I'd instead recommend using{}id_/{}, since it retrieves the file exactly as downloaded.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.