Skip to content

Commit

Permalink
feat(cli): allow running all directory entries
Browse files Browse the repository at this point in the history
  • Loading branch information
hougesen committed Oct 29, 2023
1 parent fffa7ba commit d76aa00
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 27 deletions.
1 change: 1 addition & 0 deletions hitt-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ name = "hitt"
path = "src/main.rs"

[dependencies]
async-recursion = "1.0.5"
clap = { version = "4.3.24", features = ["derive"] }
hitt-parser = { path = "../hitt-parser" }
hitt-request = { path = "../hitt-request" }
Expand Down
4 changes: 4 additions & 0 deletions hitt-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ pub(crate) struct CliArguments {
/// Disable pretty printing of response body
#[arg(long, default_value_t = false)]
pub(crate) disable_formatting: bool,

/// Enable to run directory recursively
#[arg(long, short, default_value_t = false)]
pub(crate) recursive: bool,
}
88 changes: 88 additions & 0 deletions hitt-cli/src/fs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use async_recursion::async_recursion;
use hitt_request::send_request;

use crate::{
config::CliArguments,
printing::{handle_response, print_error},
};

async fn get_file_content(path: std::path::PathBuf) -> Result<String, std::io::Error> {
let buffr = tokio::fs::read(path).await?;

Ok(String::from_utf8_lossy(&buffr).to_string())
}

pub(crate) async fn is_directory(path: &std::path::Path) -> Result<bool, std::io::Error> {
tokio::fs::metadata(path).await.map(|m| m.is_dir())
}

pub(crate) async fn handle_file(
http_client: &reqwest::Client,
path: std::path::PathBuf,
args: &CliArguments,
) -> Result<(), std::io::Error> {
println!("hitt: running {path:?}");

let fcontent = get_file_content(path).await?;

for req in hitt_parser::parse_requests(&fcontent).unwrap() {
match send_request(http_client, &req).await {
Ok(response) => handle_response(response, args),
Err(request_error) => {
print_error(format!(
"error sending request {} {}\n{request_error:#?}",
req.method, req.uri,
));
std::process::exit(1);
}
}
}

Ok(())
}

async fn handle_dir_entry(
http_client: &reqwest::Client,
entry: tokio::fs::DirEntry,
args: &CliArguments,
) -> Result<(), std::io::Error> {
let metadata = entry.metadata().await?;

match metadata.is_dir() {
true => handle_dir(http_client, entry.path(), args).await,
false => {
let entry_path = entry.path();

if let Some(ext) = entry_path.extension() {
if ext == "http" {
return handle_file(http_client, entry_path, args).await;
}
}

Ok(())
}
}
}

#[async_recursion]
pub(crate) async fn handle_dir(
http_client: &reqwest::Client,
path: std::path::PathBuf,
args: &CliArguments,
) -> Result<(), std::io::Error> {
if !args.recursive {
print_error(format!(
"{path:?} is a directory, but the recursive argument was not supplied"
));

std::process::exit(1);
}

let mut read_dir_result = tokio::fs::read_dir(&path).await?;

while let Some(entry) = read_dir_result.next_entry().await? {
handle_dir_entry(http_client, entry, args).await?;
}

Ok(())
}
49 changes: 27 additions & 22 deletions hitt-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,44 @@ use std::str::FromStr;

use clap::Parser;
use config::CliArguments;
use hitt_request::send_request;
use printing::print_response;
use fs::{handle_dir, handle_file, is_directory};
use printing::print_error;

mod config;
mod fs;
mod printing;

async fn get_file_content(path: std::path::PathBuf) -> Result<String, std::io::Error> {
let buffr = tokio::fs::read(path).await?;

Ok(String::from_utf8_lossy(&buffr).to_string())
async fn run(
http_client: &reqwest::Client,
path: std::path::PathBuf,
args: &CliArguments,
) -> Result<(), std::io::Error> {
match is_directory(&path).await {
Ok(true) => handle_dir(http_client, path, args).await,
Ok(false) => handle_file(http_client, path, args).await,
Err(io_error) => {
print_error(format!(
"error checking if {path:?} is a directory\n{io_error:#?}"
));
std::process::exit(1);
}
}
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> Result<(), std::io::Error> {
let args = CliArguments::parse();

let http_client = reqwest::Client::new();

let path = std::path::PathBuf::from_str(&args.path)?;

let fcontent = get_file_content(path).await?;

for req in hitt_parser::parse_requests(&fcontent).unwrap() {
match send_request(&http_client, &req).await {
Ok(response) => {
print_response(response, &args);
}
Err(request_error) => panic!(
"Error sending request {} {}\n{:#?}",
req.method, req.uri, request_error,
),
match std::path::PathBuf::from_str(&args.path) {
Ok(path) => run(&http_client, path, &args).await,
Err(parse_path_error) => {
print_error(format!(
"error parsing path {} as filepath\n{parse_path_error:#?}",
args.path
));
std::process::exit(1);
}
}

Ok(())
}
2 changes: 1 addition & 1 deletion hitt-cli/src/printing/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn format_json(input: &str) -> String {

#[inline]
fn __print_body(body: &str) {
println!("{TEXT_YELLOW}{body}{TEXT_RESET}")
println!("\n{TEXT_YELLOW}{body}{TEXT_RESET}")
}

#[inline]
Expand Down
4 changes: 3 additions & 1 deletion hitt-cli/src/printing/headers.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::printing::{TEXT_RESET, TEXT_YELLOW};

use super::print_error;

#[inline]
pub(crate) fn print_headers(headers: &reqwest::header::HeaderMap) {
for (key, value) in headers {
if let Ok(value) = value.to_str() {
println!("{TEXT_YELLOW}{key}{TEXT_RESET}: {value}{TEXT_RESET}");
} else {
eprintln!("Error printing value for header: {key}");
print_error(format!("error printing value for header: {key}"));
}
}
}
9 changes: 6 additions & 3 deletions hitt-cli/src/printing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub const TEXT_YELLOW: &str = "\x1B[33m";

pub const TEXT_RESET: &str = "\x1B[39m";

pub(crate) fn print_response(response: HittResponse, args: &CliArguments) {
pub(crate) fn handle_response(response: HittResponse, args: &CliArguments) {
print_status(
&response.http_version,
&response.method,
Expand All @@ -41,8 +41,6 @@ pub(crate) fn print_response(response: HittResponse, args: &CliArguments) {
.get("content-type")
.map(|x| x.to_str().expect("response content-type to be valid"));

println!();

print_body(&response.body, content_type, args.disable_formatting);
}

Expand All @@ -53,3 +51,8 @@ pub(crate) fn print_response(response: HittResponse, args: &CliArguments) {
std::process::exit(0);
}
}

#[inline]
pub fn print_error(message: String) {
eprintln!("{TEXT_RED}hitt: {message}{TEXT_RESET}")
}

0 comments on commit d76aa00

Please sign in to comment.