Skip to content

Commit

Permalink
feat: displaying error messages on request
Browse files Browse the repository at this point in the history
  • Loading branch information
wllfaria committed May 27, 2024
1 parent 0b7a9ed commit 513d4fd
Show file tree
Hide file tree
Showing 15 changed files with 607 additions and 225 deletions.
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions reqtui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ tree-sitter-json.workspace = true
lazy_static.workspace = true

ropey = "1.6.1"
jsonxf = "1.1.1"
async-trait = "0.1.80"

[build-dependencies]
Expand Down
30 changes: 14 additions & 16 deletions reqtui/src/net/request_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,24 @@ use tokio::sync::mpsc::UnboundedSender;
pub struct Response {
pub body: Option<String>,
pub pretty_body: Option<TextObject<Readonly>>,
pub headers: HeaderMap<HeaderValue>,
pub headers: Option<HeaderMap<HeaderValue>>,
pub duration: Duration,
pub status: reqwest::StatusCode,
pub headers_size: u64,
pub body_size: u64,
pub size: u64,
pub status: Option<reqwest::StatusCode>,
pub headers_size: Option<u64>,
pub body_size: Option<u64>,
pub size: Option<u64>,
pub is_error: bool,
pub cause: Option<String>,
}

pub struct RequestManager;

impl RequestManager {
pub async fn handle<S>(strategy: S, request: Request) -> anyhow::Result<Response>
pub async fn handle<S>(strategy: S, request: Request) -> Response
where
S: RequestStrategy,
{
let response = strategy.handle(request).await?;
Ok(response)
strategy.handle(request).await
}
}

Expand Down Expand Up @@ -59,20 +60,17 @@ impl From<&str> for ContentType {
pub fn handle_request(request: Request, response_tx: UnboundedSender<Response>) {
tracing::debug!("starting to handle user request");
tokio::spawn(async move {
let result = match request.body_type.as_ref() {
let response = match request.body_type.as_ref() {
// if we dont have a body type, this is a GET request, so we use HTTP strategy
None => RequestManager::handle(HttpResponse, request).await,
Some(body_type) => match body_type {
BodyType::Json => RequestManager::handle(HttpResponse, request).await,
},
};

match result {
Ok(response) => response_tx.send(response).ok(),
Err(e) => {
tracing::error!("{e:?}");
todo!();
}
}
response_tx
.send(response)
.is_err()
.then(|| std::process::abort());
});
}
2 changes: 1 addition & 1 deletion reqtui/src/net/request_strategies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ use crate::{collection::types::Request, net::request_manager::Response};

#[async_trait::async_trait]
pub trait RequestStrategy {
async fn handle(&self, request: Request) -> anyhow::Result<Response>;
async fn handle(&self, request: Request) -> Response;
}
103 changes: 66 additions & 37 deletions reqtui/src/net/request_strategies/http_strategy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::error::Error;

use crate::{
collection::types::{Request, RequestMethod},
net::{
Expand All @@ -13,7 +11,7 @@ pub struct HttpResponse;

#[async_trait::async_trait]
impl RequestStrategy for HttpResponse {
async fn handle(&self, request: Request) -> anyhow::Result<Response> {
async fn handle(&self, request: Request) -> Response {
let client = reqwest::Client::new();

match request.method {
Expand All @@ -27,30 +25,29 @@ impl RequestStrategy for HttpResponse {
}

impl HttpResponse {
async fn handle_get_request(
&self,
client: reqwest::Client,
request: Request,
) -> anyhow::Result<Response> {
async fn handle_get_request(&self, client: reqwest::Client, request: Request) -> Response {
let now = std::time::Instant::now();
match client.get(request.uri).send().await {
Ok(response) => {
let decoder = decoder_from_headers(response.headers());
decoder.decode(response, now).await
}
Err(e) => {
tracing::error!("{:?}", e.source());
tracing::debug!("{e:?}");
todo!();
}
Err(e) => Response {
is_error: true,
cause: Some(e.to_string()),
body: None,
pretty_body: None,
body_size: None,
size: None,
headers_size: None,
status: None,
headers: None,
duration: now.elapsed(),
},
}
}

async fn handle_post_request(
&self,
client: reqwest::Client,
request: Request,
) -> anyhow::Result<Response> {
async fn handle_post_request(&self, client: reqwest::Client, request: Request) -> Response {
let now = std::time::Instant::now();
match client
.post(request.uri)
Expand All @@ -62,15 +59,22 @@ impl HttpResponse {
let decoder = decoder_from_headers(response.headers());
decoder.decode(response, now).await
}
Err(_) => todo!(),
Err(e) => Response {
is_error: true,
cause: Some(e.to_string()),
body: None,
pretty_body: None,
body_size: None,
size: None,
headers_size: None,
status: None,
headers: None,
duration: now.elapsed(),
},
}
}

async fn handle_put_request(
&self,
client: reqwest::Client,
request: Request,
) -> anyhow::Result<Response> {
async fn handle_put_request(&self, client: reqwest::Client, request: Request) -> Response {
let now = std::time::Instant::now();
match client
.put(request.uri)
Expand All @@ -82,15 +86,22 @@ impl HttpResponse {
let decoder = decoder_from_headers(response.headers());
decoder.decode(response, now).await
}
Err(_) => todo!(),
Err(e) => Response {
is_error: true,
cause: Some(e.to_string()),
body: None,
pretty_body: None,
body_size: None,
size: None,
headers_size: None,
status: None,
headers: None,
duration: now.elapsed(),
},
}
}

async fn handle_patch_request(
&self,
client: reqwest::Client,
request: Request,
) -> anyhow::Result<Response> {
async fn handle_patch_request(&self, client: reqwest::Client, request: Request) -> Response {
let now = std::time::Instant::now();
match client
.patch(request.uri)
Expand All @@ -102,15 +113,22 @@ impl HttpResponse {
let decoder = decoder_from_headers(response.headers());
decoder.decode(response, now).await
}
Err(_) => todo!(),
Err(e) => Response {
is_error: true,
cause: Some(e.to_string()),
body: None,
pretty_body: None,
body_size: None,
size: None,
headers_size: None,
status: None,
headers: None,
duration: now.elapsed(),
},
}
}

async fn handle_delete_request(
&self,
client: reqwest::Client,
request: Request,
) -> anyhow::Result<Response> {
async fn handle_delete_request(&self, client: reqwest::Client, request: Request) -> Response {
let now = std::time::Instant::now();
match client
.delete(request.uri)
Expand All @@ -122,7 +140,18 @@ impl HttpResponse {
let decoder = decoder_from_headers(response.headers());
decoder.decode(response, now).await
}
Err(_) => todo!(),
Err(e) => Response {
is_error: true,
cause: Some(e.to_string()),
body: None,
pretty_body: None,
body_size: None,
size: None,
headers_size: None,
status: None,
headers: None,
duration: now.elapsed(),
},
}
}
}
3 changes: 1 addition & 2 deletions reqtui/src/net/response_decoders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ use std::time::Instant;

#[async_trait::async_trait]
pub trait ResponseDecoder {
async fn decode(&self, response: reqwest::Response, start: Instant)
-> anyhow::Result<Response>;
async fn decode(&self, response: reqwest::Response, start: Instant) -> Response;
}

pub fn decoder_from_headers(headers: &HeaderMap) -> impl ResponseDecoder {
Expand Down
30 changes: 16 additions & 14 deletions reqtui/src/net/response_decoders/json_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ pub struct JsonDecoder;

#[async_trait::async_trait]
impl ResponseDecoder for JsonDecoder {
async fn decode(
&self,
response: reqwest::Response,
start: Instant,
) -> anyhow::Result<Response> {
async fn decode(&self, response: reqwest::Response, start: Instant) -> Response {
let duration = start.elapsed();
let headers = response.headers().to_owned();
let status = response.status();
let headers = Some(response.headers().to_owned());
let status = Some(response.status());
let headers_size: u64 = response
.headers()
.iter()
Expand All @@ -24,23 +20,29 @@ impl ResponseDecoder for JsonDecoder {

let mut body: Option<String> = None;
let mut pretty_body = None;

if response.content_length().is_some_and(|len| len.gt(&0)) {
body = Some(response.json().await?);
pretty_body = Some(TextObject::from(&serde_json::to_string_pretty(&body)?));
if let Ok(body_str) = response.text().await {
let pretty_body_str = jsonxf::pretty_print(&body_str).unwrap_or_default();
pretty_body = Some(TextObject::from(&pretty_body_str));
body = Some(body_str);
};
}

let body_size = body.as_ref().map(|body| body.len()).unwrap_or_default() as u64;
let size = headers_size.add(body_size);

Ok(Response {
Response {
body,
pretty_body,
headers,
duration,
status,
size,
headers_size,
body_size,
})
size: Some(size),
headers_size: Some(headers_size),
body_size: Some(body_size),
cause: None,
is_error: false,
}
}
}
1 change: 1 addition & 0 deletions tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ tui-big-text = { version = "0.4.3" }
tracing-subscriber = { version = "0.3.18" }
tracing-appender = "0.2.3"
uuid = { version = "1.8.0", features = ["v4", "fast-rng", "macro-diagnostics"] }
rand = "0.8.5"

[dev-dependencies]
tempfile = "3.10.1"
Expand Down
Loading

0 comments on commit 513d4fd

Please sign in to comment.