From 482e93d8673c54603295007f9d08bafc492c9451 Mon Sep 17 00:00:00 2001 From: Integralist Date: Wed, 27 Mar 2024 10:42:53 +0000 Subject: [PATCH] feat: display response body --- Cargo.lock | 191 ++++++++++++++++++++++++++++---------- Cargo.toml | 10 +- Makefile | 12 ++- src/app.rs | 12 +++ src/args.rs | 5 +- src/styles.rs | 3 + tests/integration_test.rs | 2 +- 7 files changed, 174 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31d5903..6228b36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.78" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca87830a3e3fb156dc96cfbd31cb620265dd053be734723f22b760d6cc3c3051" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "autocfg" @@ -145,9 +145,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.12" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck", "proc-macro2", @@ -179,9 +179,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" @@ -207,7 +207,7 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crs" -version = "1.0.0" +version = "1.1.0" dependencies = [ "anyhow", "clap", @@ -289,6 +289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -323,6 +324,7 @@ checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-core", "futures-io", + "futures-sink", "futures-task", "memchr", "pin-project-lite", @@ -338,9 +340,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.22" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" dependencies = [ "bytes", "fnv", @@ -363,9 +365,9 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -384,9 +386,9 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "http" -version = "0.2.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -395,12 +397,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.4" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", + "futures-core", "http", + "http-body", "pin-project-lite", ] @@ -410,47 +424,60 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - [[package]] name = "hyper" -version = "0.14.28" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "h2", "http", "http-body", "httparse", - "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", + "http-body-util", "hyper", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -541,12 +568,9 @@ checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "log" -version = "0.4.16" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "matches" @@ -677,6 +701,26 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.41", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -724,9 +768,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -736,9 +780,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -762,20 +806,23 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.23" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" dependencies = [ "base64", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2", "http", "http-body", + "http-body-util", "hyper", "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", @@ -784,9 +831,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -817,6 +866,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + [[package]] name = "ryu" version = "1.0.9" @@ -891,6 +949,12 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "socket2" version = "0.5.5" @@ -903,9 +967,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "supports-color" @@ -939,6 +1003,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -1035,6 +1105,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.1" @@ -1047,6 +1139,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] diff --git a/Cargo.toml b/Cargo.toml index 88f5baf..37dd87c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crs" -version = "1.0.0" +version = "1.1.0" edition = "2021" license = "MIT" description = "A CLI that can make a HTTP request, then sort, filter and display the HTTP response headers." @@ -12,11 +12,11 @@ keywords = ["cli", "http"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.78" -clap = { version = "4.4.12", features = ["derive"] } +anyhow = "1.0.81" +clap = { version = "4.5.4", features = ["derive"] } owo-colors = { version = "4.0.0", features = ["supports-colors"] } -regex = "1.10.2" -reqwest = { version = "0.11.23", features = ["blocking"] } +regex = "1.10.4" +reqwest = { version = "0.12.2", features = ["blocking"] } [dev-dependencies] test_bin = "0.4.0" diff --git a/Makefile b/Makefile index fd1f0ab..33d75db 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ .DEFAULT_GOAL := release +TEST_URL ?= "https://httpbin.org/anything" + # Compilation check .PHONY: check check: ## Validate app can compile @@ -23,7 +25,7 @@ release: ## Generate release binary # Validate release build .PHONY: release-example release-example: ## Run release binary - ./target/release/crs --filter vary,cache https://www.fastly.com + ./target/release/crs --filter server,content $(TEST_URL) # Run application code .PHONY: run-example @@ -32,18 +34,18 @@ run: ## Run app with custom args (e.g. ARGS=--help) # Validate runtime code .PHONY: run-example -run-example: ## Run app using www.fastly.com - cargo run -- --filter vary,cache https://www.fastly.com +run-example: ## Run app using TEST_URL + include response body + cargo run -- --filter server,content --body $(TEST_URL) # Validate runtime code with JSON output .PHONY: run-example-json run-example-json: ## Run app and expect JSON output - cargo run -- --filter vary,cache https://www.fastly.com --json | jq + cargo run -- --filter server,content $(TEST_URL) --json | jq # Validate runtime code with expected failure .PHONY: run-example-failure run-example-failure: ## Run app but expect error output - cargo run -- --filter vary,cache https://www.fastly.com/does-not-exist + cargo run -- --filter server,content https://httpbin.org/status/404 .PHONY: help help: diff --git a/src/app.rs b/src/app.rs index 81ada86..39e9cdd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,7 +1,9 @@ use crate::args::Args; use crate::headers::Headers; +use crate::styles::Styles; use anyhow::{Context, Result}; use clap::Parser; +use owo_colors::{OwoColorize, Stream::Stdout}; use std::ffi::OsString; use std::io::Write; @@ -45,5 +47,15 @@ fn exec(args: Args, output: &mut W) -> Result<()> { let mut headers = Headers::new(resp.headers(), args.filter, output); headers.parse()?.display(args.json, resp.status())?; + if args.body { + let style = Styles::new().body; + write!( + output, + "\n\n{}:\n\n{}", + "Response Body".if_supports_color(Stdout, |text| text.style(style)), + resp.text().unwrap() + )?; + }; + Ok(()) } diff --git a/src/args.rs b/src/args.rs index 6387898..0a2947d 100644 --- a/src/args.rs +++ b/src/args.rs @@ -5,7 +5,7 @@ pub const ABOUT: &str = "A CLI that can make a HTTP request, then sort, filter and display the HTTP response headers."; #[derive(Parser, Debug)] -#[clap(author, version = "1.0.0", about = ABOUT)] +#[clap(author, version = "1.1.0", about = ABOUT)] #[clap(group( ArgGroup::new("format") .args(&["json", "color"]), @@ -20,6 +20,9 @@ pub struct Args { /// Output is formatted into JSON #[clap(short, long)] pub json: bool, + /// Output includes response body (incompatible with --json) + #[clap(short, long)] + pub body: bool, /// URL to request pub url: String, } diff --git a/src/styles.rs b/src/styles.rs index cb5eaff..b6c2d29 100644 --- a/src/styles.rs +++ b/src/styles.rs @@ -6,6 +6,7 @@ pub struct Styles { pub heading: Style, pub status: Style, pub status_bad: Style, + pub body: Style, } impl Styles { @@ -13,11 +14,13 @@ impl Styles { let heading = Style::new().black().on_bright_yellow().bold(); let status = Style::new().black().on_bright_green().bold(); let status_bad = Style::new().black().on_bright_red().bold(); + let body = Style::new().black().on_bright_blue().bold(); Self { heading, status, status_bad, + body, } } } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 0185c24..014e859 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -23,5 +23,5 @@ fn version_output() { let output = String::from_utf8_lossy(&output.stdout); println!("{:?}", output); - assert!(output.contains("crs 1.0.0")); + assert!(output.contains("crs 1.1.0")); }