cetar 0.1.6

💥 CURL execution timing analyzer
Documentation
#![allow(dead_code)]
use cetar::{make_color, print_error};
use clap::Parser;

#[derive(Parser, Debug)]
#[command(name = "cetar", about = "💥 CURL execution timing analyzer", version, long_about = None)]
struct Args {
    url: String,

    #[clap(
        short = 'X',
        long,
        default_value = "GET",
        help = "Available methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH"
    )]
    method: String,

    #[clap(
        short = 'H',
        long,
        help = "Pass custom header(s) to server, example: -H 'Accept: application/json'"
    )]
    headers: Vec<cetar::network::Header>,

    #[clap(
        short,
        long,
        help = "HTTP request data to send, example: -d 'key=value' -d @file.json -d '{\"key\": \"value\"}'"
    )]
    data: Option<String>,

    #[clap(short, long, help = "Write output to <file>")]
    output: Option<String>,

    #[clap(short = 'l', long = "location", help = "Follow HTTP 3xx redirects")]
    follow_redirects: bool,

    #[clap(short, long, help = "Verbose output")]
    verbose: bool,

    #[clap(short = 'B', long, help = "Display response body")]
    display_response_body: bool,

    #[clap(short = 'G', long, help = "Display response headers")]
    display_response_headers: bool,

    #[clap(
        long,
        default_value = "cyan",
        help = "Main output color, available colors: black, red, green, yellow, blue, magenta, cyan, white"
    )]
    color: String,
}

impl TryFrom<Args> for cetar::network::Config<'_> {
    type Error = anyhow::Error;

    fn try_from(cli: Args) -> Result<Self, Self::Error> {
        let data = if let Some(d) = cli.data {
            match d.starts_with('@') {
                true => std::fs::read_to_string(&d[1..])?,
                false => d,
            }
            .into()
        } else {
            None
        };

        Ok(Self {
            url: cli.url.into(),
            request_headers: cli.headers,
            request_body: data.map(|x| x.into()),
            method: cli.method.as_str().try_into()?,
            color: cli.color.as_str().try_into()?,
            output: cli.output.map(|x| x.into()),
            display_response_body: cli.display_response_body,
            display_response_headers: cli.display_response_headers,
            follow_redirects: cli.follow_redirects,
            verbose: cli.verbose,
        })
    }
}

fn execute() -> anyhow::Result<()> {
    let parsed = Args::parse();
    let config = cetar::network::Config::try_from(parsed)?;
    let result = cetar::network::send_request(&config)?;

    cetar::output::handle_output(&config, &result)?;
    cetar::output::Screen::new(&config, &result).display();

    Ok(())
}

fn main() {
    if let Err(e) = execute() {
        print_error!("Error: {}", e);
    }
}