Skip to content
This repository has been archived by the owner on Oct 8, 2024. It is now read-only.

Commit

Permalink
fix: remove duplicate options stored on the app struct
Browse files Browse the repository at this point in the history
  • Loading branch information
PThorpe92 committed Apr 21, 2024
1 parent 04991a4 commit 8fc4766
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 123 deletions.
127 changes: 31 additions & 96 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ pub struct App<'a> {
pub selected: Option<usize>,
/// command (curl or wget)
pub command: Curl,
/// vec of applicable options
pub opts: Vec<AppOptions>,
/// Input struct for tui_input dependency
pub input: Input,
/// vec for user input to push into
Expand Down Expand Up @@ -64,7 +62,6 @@ impl<'a> Default for App<'a> {
command: Curl::default(),
input_mode: InputMode::Normal,
messages: Vec::new(),
opts: Vec::new(),
items: Screen::Home.get_opts(None),
input: Input::default(),
state: None,
Expand Down Expand Up @@ -214,7 +211,7 @@ impl<'a> App<'a> {
}

pub fn get_request_body(&self) -> Option<String> {
self.opts.iter().find_map(|opt| match opt {
self.command.opts.iter().find_map(|opt| match opt {
AppOptions::RequestBody(body) => Some(body.clone()),
_ => None,
})
Expand Down Expand Up @@ -325,9 +322,7 @@ impl<'a> App<'a> {
}

pub fn execute_command(&mut self) -> Result<(), String> {
let opts = &self.opts;
self.command
.execute(Some(Box::new(self.db.deref_mut())), opts.as_slice())
self.command.execute(Some(Box::new(self.db.deref_mut())))
}

pub fn import_postman_collection(
Expand All @@ -352,9 +347,8 @@ impl<'a> App<'a> {
let mut command: Curl = serde_json::from_str(json)
.map_err(|e| e.to_string())
.unwrap();
let opts = &self.opts;
command.easy_from_opts(opts.as_slice());
match command.execute(None, opts.as_slice()) {
command.easy_from_opts();
match command.execute(None) {
Ok(_) => self.set_response(&command.get_response().unwrap_or("".to_string())),
Err(e) => self.set_response(&e),
};
Expand Down Expand Up @@ -390,18 +384,20 @@ impl<'a> App<'a> {

pub fn remove_app_option(&mut self, opt: &AppOptions) {
self.command.remove_option(opt);
self.opts
self.command
.opts
.retain(|x| mem::discriminant(x) != mem::discriminant(opt));
}

pub fn clear_all_options(&mut self) {
self.opts.clear();
self.command.opts.clear();
self.messages.clear();
self.response = None;
}

fn has_app_option(&self, opt: &AppOptions) -> bool {
self.opts
self.command
.opts
.iter()
.any(|x| mem::discriminant(x) == mem::discriminant(opt))
}
Expand All @@ -425,7 +421,7 @@ impl<'a> App<'a> {
return;
}
if opt.should_toggle() {
self.opts.push(opt.clone());
self.command.opts.push(opt.clone());
self.command.add_option(&opt);
}
self.redraw();
Expand All @@ -437,87 +433,21 @@ impl<'a> App<'a> {
return;
}
if self.should_add_option(&opt) {
self.opts.push(opt.clone());
self.command.opts.push(opt.clone());
self.command.add_option(&opt);
} else {
self.handle_replace(opt.clone());
self.handle_replace(&opt);
}
self.selected = None;
}

fn handle_replace(&mut self, mut opt: AppOptions) {
for option in self.opts.iter_mut() {
match option {
AppOptions::URL(_) => {
if let AppOptions::URL(ref url) = opt {
self.command.set_url(url);
option.replace_value(url.clone());
}
}
AppOptions::Outfile(_) => {
if let AppOptions::Outfile(ref outfile) = opt {
option.replace_value(outfile.clone());
self.command.set_outfile(outfile);
}
}
AppOptions::Response(_) => {
if let AppOptions::Response(ref response) = opt {
option.replace_value(opt.clone().get_value());
self.command.set_response(response);
}
}
AppOptions::Auth(_) => {} // This is handled by the screen
AppOptions::UserAgent(_) => {
if let AppOptions::UserAgent(ref agent) = opt {
option.replace_value(String::from(agent));
self.command.set_user_agent(agent);
}
}
AppOptions::Referrer(_) => {
if let AppOptions::Referrer(ref referrer) = opt {
option.replace_value(String::from(referrer));
self.command.set_referrer(referrer);
}
}
AppOptions::CookiePath(_) => {
if let AppOptions::CookiePath(ref mut cookie) = opt {
option.replace_value(cookie.clone());
self.command.add_cookie(cookie);
}
}
AppOptions::CookieJar(_) => {
if let AppOptions::CookieJar(ref mut cookie) = opt {
option.replace_value(cookie.clone());
self.command.set_cookie_jar(cookie);
}
}
AppOptions::CaPath(_) => {
if let AppOptions::CaPath(ref ca_path) = opt {
option.replace_value(String::from(ca_path));
self.command.set_ca_path(ca_path);
}
}
AppOptions::MaxRedirects(_) => {
if let AppOptions::MaxRedirects(ref max_redirects) = opt {
option.replace_value(max_redirects.to_string());
self.command.set_max_redirects(*max_redirects);
}
}
AppOptions::UnixSocket(_) => {
if let AppOptions::UnixSocket(ref mut socket) = opt {
option.replace_value(socket.clone());
self.command.set_unix_socket(socket);
}
}
AppOptions::RequestBody(_) => {
if let AppOptions::RequestBody(ref mut body) = opt {
option.replace_value(body.clone());
self.command.set_request_body(body);
}
}
_ => {}
}
}
fn handle_replace(&mut self, opt: &AppOptions) {
self.command
.opts
.retain(|option| std::mem::discriminant(option) != std::mem::discriminant(opt));
self.command.remove_option(opt);
self.command.add_option(opt);
self.command.opts.push(opt.clone());
}
}
#[cfg(test)]
Expand Down Expand Up @@ -567,7 +497,7 @@ pub mod tests {
"hello world".to_string(),
));
app.add_app_option(crate::display::AppOptions::Headers(
"Content-Type: Application/json".to_string(),
"Content-Type: application/json".to_string(),
));
app.command.set_request_body("hello world");
app.command.set_method(crate::request::curl::Method::Put);
Expand All @@ -582,15 +512,16 @@ pub mod tests {
.match_header("Content-Type", "application/json")
.assert();
assert_eq!(
app.opts
app.command
.opts
.iter()
.find(|x| x
== &&crate::display::AppOptions::ContentHeaders(
crate::display::HeaderKind::ContentType("application/json".to_string())
))
.unwrap()
.get_curl_flag_value(),
"-H \"Content-Type: Application/json\""
"-H \"Content-Type: application/json\""
);
}
#[test]
Expand Down Expand Up @@ -670,7 +601,8 @@ pub mod tests {
token.to_string(),
)));
assert_eq!(
app.opts
app.command
.opts
.iter()
.find(|x| x
== &&crate::display::AppOptions::Auth(AuthKind::Bearer(token.to_string())))
Expand All @@ -689,7 +621,8 @@ pub mod tests {
user, pass
))));
assert_eq!(
app.opts
app.command
.opts
.iter()
.find(|x| x
== &&crate::display::AppOptions::Auth(AuthKind::Basic(format!(
Expand All @@ -711,7 +644,8 @@ pub mod tests {
user, pass
))));
assert_eq!(
app.opts
app.command
.opts
.iter()
.find(|x| x
== &&crate::display::AppOptions::Auth(AuthKind::Digest(format!(
Expand All @@ -728,7 +662,8 @@ pub mod tests {
let mut app = App::default();
app.add_app_option(crate::display::AppOptions::Auth(AuthKind::Ntlm));
assert_eq!(
app.opts
app.command
.opts
.iter()
.find(|x| x == &&crate::display::AppOptions::Auth(AuthKind::Ntlm))
.unwrap()
Expand Down
16 changes: 6 additions & 10 deletions src/request/curl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct Curl {
headers: Option<Vec<String>>,
url: String,
// Build this on the App struct and pass it here to store for serialization
opts: Vec<AppOptions>,
pub opts: Vec<AppOptions>,
resp: Option<String>,
upload_file: Option<String>,
outfile: Option<String>,
Expand Down Expand Up @@ -308,9 +308,8 @@ impl Curl {
}

#[rustfmt::skip]
pub fn execute(&mut self, mut db: Option<Box<&mut DB>>, opts: &[AppOptions]) -> Result<(), String> {
pub fn execute(&mut self, mut db: Option<Box<&mut DB>>) -> Result<(), String> {
let mut list = List::new();
self.opts = opts.to_vec();
curl::init();
// we do this again because if it's a patch | put and there's a
// body, it will default to post
Expand Down Expand Up @@ -555,15 +554,12 @@ impl Curl {
self.save.1
}

// This is a hack because when we deseialize json from the DB, we get a curl struct with no curl::Easy
// field, so we have to manually add, then set the options one at a time from the opts vector.
// ANY time we get a command from the database to run, we have to call this method first.
pub fn easy_from_opts(&mut self, opts: &[AppOptions]) {
pub fn easy_from_opts(&mut self) {
self.build_command_string();
let url = self.url.clone();
self.set_url(&url);
self.curl.url(&self.url).unwrap();
self.apply_method();
for opt in opts {
let opts = self.opts.clone();
for opt in opts.iter() {
self.add_option(opt);
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/screens/input/input_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub fn handle_default_input_screen(app: &mut App, frame: &mut Frame<'_>, opt: In
String::from("Error: You have already entered a URL"),
))));
}
let socket = app.opts.iter().find_map(|f| {
let socket = app.command.opts.iter().find_map(|f| {
if let AppOptions::UnixSocket(s) = f {
Some(s)
} else {
Expand All @@ -126,7 +126,7 @@ pub fn handle_default_input_screen(app: &mut App, frame: &mut Frame<'_>, opt: In
}
}
InputOpt::CookiePath => {
if let Some(cookie) = app.opts.iter().find_map(|f| {
if let Some(cookie) = app.command.opts.iter().find_map(|f| {
if let AppOptions::CookiePath(s) = f {
Some(s)
} else {
Expand All @@ -142,7 +142,7 @@ pub fn handle_default_input_screen(app: &mut App, frame: &mut Frame<'_>, opt: In
}
}
InputOpt::CookieJar => {
if let Some(cookie) = app.opts.iter().find_map(|f| {
if let Some(cookie) = app.command.opts.iter().find_map(|f| {
if let AppOptions::CookieJar(s) = f {
Some(s)
} else {
Expand Down Expand Up @@ -361,7 +361,7 @@ pub fn parse_input(message: String, opt: InputOpt, app: &mut App) {
}
}

pub fn render_input_with_prompt(frame: &mut Frame<'_>, prompt: Text) {
pub fn render_input_with_prompt<'a, T: Into<Text<'a>>>(frame: &mut Frame<'_>, prompt: T) {
// Render the input with the provided prompt
let chunks = Layout::default()
.direction(Direction::Vertical)
Expand Down Expand Up @@ -397,9 +397,11 @@ fn parse_auth(auth: AuthKind, app: &mut App, message: &str) {
_ => AuthKind::None,
});
if app.command.has_auth() {
app.opts.retain(|x| !matches!(x, AppOptions::Auth(_)));
app.command
.opts
.retain(|x| !matches!(x, AppOptions::Auth(_)));
}
app.opts.push(AppOptions::Auth(match auth {
app.command.opts.push(AppOptions::Auth(match auth {
AuthKind::Basic(_) => AuthKind::Basic(String::from(message)),
AuthKind::Bearer(_) => AuthKind::Bearer(String::from(message)),
AuthKind::Digest(_) => AuthKind::Digest(String::from(message)),
Expand Down
22 changes: 14 additions & 8 deletions src/screens/input/request_body_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::app::{App, InputMode};
use crate::display::inputopt::InputOpt;
use crate::display::AppOptions;
use crate::screens::{centered_rect, Screen, ScreenArea};
use tui::text::{Line, Text};
use tui::style::Styled;
use tui::text::Line;
use tui::widgets::{Block, Borders, Paragraph};
use tui::{
prelude::{Constraint, Direction, Layout},
Expand All @@ -11,8 +12,6 @@ use tui::{
Frame,
};

use super::input_screen::render_input_with_prompt;

pub fn handle_req_body_input_screen(app: &mut App, frame: &mut Frame<'_>, _opt: InputOpt) {
let chunks = Layout::default()
.direction(Direction::Vertical)
Expand Down Expand Up @@ -45,19 +44,25 @@ pub fn handle_req_body_input_screen(app: &mut App, frame: &mut Frame<'_>, _opt:
Style::default(),
),
};
let prompt = Text::from(
"Enter your Request body,\nOr the file path to the body\na .json filepath will automatically add Content-Type Header\nthen press Enter to submit\n",
);
let prompt = vec![
Line::raw("Enter your Request body Or the path to a file containing the body."),
Line::raw(" "),
Line::raw("Example: {\"key\", \"value\"} (no outside quotes needed)\n"),
Line::raw(" "),
Line::raw("a .json filepath will automatically add Content-Type Header"),
Line::raw(" "),
Line::raw("then press Enter to submit"),
];
if !app.command.method.needs_reset() {
app.goto_screen(&Screen::RequestMenu(Some(InputOpt::RequestError(
String::from("Error: Request Bodies are not allowed for this HTTP method"),
))));
}

let msg = Paragraph::new(Line::from(msg));
let prompt = prompt.patch_style(style);
let prompt = Paragraph::new(prompt).set_style(style);
frame.render_widget(msg, centered_rect(frame.size(), ScreenArea::Top));
render_input_with_prompt(frame, prompt);
frame.render_widget(&prompt, chunks[0]);

let width = chunks[0].width.max(3) - 3;
let scroll = app.input.visual_scroll(width as usize);
Expand Down Expand Up @@ -97,6 +102,7 @@ pub fn handle_req_body_input_screen(app: &mut App, frame: &mut Frame<'_>, _opt:
));
app.goto_screen(&Screen::RequestMenu(None));
app.messages.clear();
return;
}
app.add_app_option(AppOptions::RequestBody(app.messages[0].clone()));
app.goto_screen(&Screen::RequestMenu(None));
Expand Down
Loading

0 comments on commit 8fc4766

Please sign in to comment.