1use crate::cli::request_data::RequestData;
7use crate::HttpResponse;
8use clap::Subcommand;
9use colored::{ColoredString, Colorize};
10use serde_json::Value;
11use std::fmt;
12use std::io::{self, Write};
13
14#[derive(Subcommand, Clone, Debug)]
15pub enum RequestCommands {
16 Get {
17 #[clap(flatten)]
18 data: RequestData,
19 },
20 Post {
21 #[clap(flatten)]
22 data: RequestData,
23 },
24 Put {
25 #[clap(flatten)]
26 data: RequestData,
27 },
28 Delete {
29 #[clap(flatten)]
30 data: RequestData,
31 },
32 Patch {
33 #[clap(flatten)]
34 data: RequestData,
35 },
36}
37
38impl fmt::Display for RequestCommands {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 Self::Get { .. } => write!(f, "GET"),
42 Self::Post { .. } => write!(f, "POST"),
43 Self::Put { .. } => write!(f, "PUT"),
44 Self::Delete { .. } => write!(f, "DELETE"),
45 Self::Patch { .. } => write!(f, "PATCH"),
46 }
47 }
48}
49
50impl RequestCommands {
51 pub fn get_data(&self) -> &RequestData {
52 match self {
54 Self::Get { data }
55 | Self::Post { data }
56 | Self::Put { data }
57 | Self::Delete { data }
58 | Self::Patch { data } => data,
59 }
60 }
61
62 pub fn print_request_method(&self, url: &str, status: u16, elapsed: u128) {
63 println!(
64 "\n[{}] {} - {} ({} ms)\n",
65 self.to_string().bold().bright_yellow(),
66 url.to_string().bold().bright_white(),
67 Self::colorize_status(status.to_string().parse().unwrap()),
68 elapsed
69 );
70 }
71
72 pub fn print_request_headers(headers: &[(String, String)]) {
73 println!("{}", "Request Headers:".to_string().bold().bright_blue());
74 for (key, value) in headers.iter() {
75 println!(" {}: {:?}", key.to_string().bright_white(), value);
76 }
77 }
78
79 pub fn print_request_body(body: &str) {
80 println!("{}", "Request Body:".to_string().bold().bright_blue());
81 println!("{}", body.italic());
82 }
83
84 pub async fn print_request_response(
85 response: &HttpResponse,
86 verbose: bool,
87 stream: bool,
88 ) -> Result<(), Box<dyn std::error::Error>> {
89 if verbose && !stream {
90 println!("{}", "Response Headers:".to_string().bold().bright_blue());
91 for (key, value) in response.headers.iter() {
92 println!(" {}: {:?}", key.to_string().bright_white(), value);
93 }
94 println!("\n{}", "Response Body:".to_string().bold().bright_blue());
95 }
96
97 if !stream {
98 if let Ok(json) = response.json::<Value>() {
100 let pretty = serde_json::to_string_pretty(&json)?;
101 println!("{}", pretty.green());
102 } else {
103 println!("{}", response.body.italic());
104 }
105 }
106
107 Ok(())
108 }
109
110 pub fn colorize_status(status: u16) -> ColoredString {
111 match status {
112 200..=299 => status.to_string().bold().bright_green(),
113 300..=499 => status.to_string().bold().bright_yellow(),
114 500..=599 => status.to_string().bold().bright_red(),
115 _ => status.to_string().white(),
116 }
117 }
118
119 pub fn prompt_missing_header_data(mut headers: Vec<(String, String)>) -> Vec<(String, String)> {
120 for header in headers.iter_mut() {
121 if header.1.contains(":?") {
122 eprint!(
123 "Header value for key '{}' is missing data. Please provide the correct value: ",
124 header.0
125 );
126 io::stdout().flush().ok();
127 let mut new_value = String::new();
128 std::io::stdin()
129 .read_line(&mut new_value)
130 .expect("Failed to read header value");
131 header.1 = new_value.trim().to_string();
132 }
133 }
134 headers
135 }
136
137 pub fn prompt_missing_body_data(mut body: String) -> String {
138 while let Some(idx) = body.find(":?") {
139 eprint!(
140 "Missing data at position {} - {}. Please provide the correct value: ",
141 idx, body
142 );
143 io::stdout().flush().ok();
144 let mut replacement = String::new();
145 std::io::stdin()
146 .read_line(&mut replacement)
147 .expect("Failed to read body placeholder");
148 let replacement = replacement.trim();
149 body.replace_range(idx..idx + 2, replacement);
150 }
151 body
152 }
153
154 pub fn is_text_data(data: &[u8]) -> bool {
156 std::str::from_utf8(data).is_ok()
157 }
158}