mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-01-11 20:00:29 +01:00
More response info
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n SELECT id, model, workspace_id, request_id, updated_at, created_at, url,\n status, status_reason, content_length, body_path, elapsed, error,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE id = ?\n ",
|
||||
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE id = ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -64,13 +64,28 @@
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"name": "elapsed_headers",
|
||||
"ordinal": 12,
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"ordinal": 13,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "version",
|
||||
"ordinal": 14,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "remote_addr",
|
||||
"ordinal": 15,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
|
||||
"ordinal": 13,
|
||||
"ordinal": 16,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -90,9 +105,12 @@
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "679a519475adeb50abf046114d3c0d1e48e103f2bb11ef47637d7f0b00ed241f"
|
||||
"hash": "0fa6b56f8c996d14908a56928674b4b35af5fa36f63dc48b9b66ee6dfde78976"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n INSERT INTO http_responses (\n id,\n request_id,\n workspace_id,\n elapsed,\n url,\n status,\n status_reason,\n content_length,\n body_path,\n headers\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 10
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "198bd086ccc87d2e6c24cb1c717f486d3ab58c0c958ede850c018fc266eade87"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n UPDATE http_responses SET (\n elapsed,\n url,\n status,\n status_reason,\n content_length,\n body_path,\n error,\n headers,\n updated_at\n ) = (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) WHERE id = ?;\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 9
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "294cbe19f9ddd9519ace3558df4308948082ec0ce7096855aa7d8fba519b8b4f"
|
||||
}
|
||||
12
src-tauri/.sqlx/query-587aedf827b00bb706c35457a75b811317e66fc84ac0906bf5513d938121a078.json
generated
Normal file
12
src-tauri/.sqlx/query-587aedf827b00bb706c35457a75b811317e66fc84ac0906bf5513d938121a078.json
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n UPDATE http_responses SET (\n elapsed,\n elapsed_headers,\n url,\n status,\n status_reason,\n content_length,\n body_path,\n error,\n headers,\n version,\n remote_addr,\n updated_at\n ) = (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) WHERE id = ?;\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 12
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "587aedf827b00bb706c35457a75b811317e66fc84ac0906bf5513d938121a078"
|
||||
}
|
||||
12
src-tauri/.sqlx/query-a1c9a862ca6a07476cb8e7d16d73bd109c070603396a890dc717e50020d006f5.json
generated
Normal file
12
src-tauri/.sqlx/query-a1c9a862ca6a07476cb8e7d16d73bd109c070603396a890dc717e50020d006f5.json
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n INSERT INTO http_responses (\n id,\n request_id,\n workspace_id,\n elapsed,\n elapsed_headers,\n url,\n status,\n status_reason,\n content_length,\n body_path,\n headers,\n version,\n remote_addr\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 13
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a1c9a862ca6a07476cb8e7d16d73bd109c070603396a890dc717e50020d006f5"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n SELECT id, model, workspace_id, request_id, updated_at, created_at, url,\n status, status_reason, content_length, body_path, elapsed, error,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE request_id = ?\n ORDER BY created_at DESC\n LIMIT ?\n ",
|
||||
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE request_id = ?\n ORDER BY created_at DESC\n LIMIT ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -64,13 +64,28 @@
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"name": "elapsed_headers",
|
||||
"ordinal": 12,
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"ordinal": 13,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "version",
|
||||
"ordinal": 14,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "remote_addr",
|
||||
"ordinal": 15,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
|
||||
"ordinal": 13,
|
||||
"ordinal": 16,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -90,9 +105,12 @@
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "07b0c398efd1d5f8f479652de658716a9e7faef6aba6583dd209a4f290c5edd1"
|
||||
"hash": "ac38621cd947c3be9ca0d8ea73325fe35c3866d16f6482fc32c23762f112dc83"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n SELECT id, model, workspace_id, request_id, updated_at, created_at, url,\n status, status_reason, content_length, body_path, elapsed, error,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE workspace_id = ?\n ORDER BY created_at DESC\n ",
|
||||
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE workspace_id = ?\n ORDER BY created_at DESC\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -64,13 +64,28 @@
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"name": "elapsed_headers",
|
||||
"ordinal": 12,
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"ordinal": 13,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "version",
|
||||
"ordinal": 14,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "remote_addr",
|
||||
"ordinal": 15,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
|
||||
"ordinal": 13,
|
||||
"ordinal": 16,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -90,9 +105,12 @@
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "3d199d371be948211f4a50c869b307f5df60784293c52397d77a187633a406dd"
|
||||
"hash": "d5e087caa163a0c7bfbbadf07eccb80105501cf5baab706aa6792dfe90af8fc9"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE http_responses ADD COLUMN elapsed_headers INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE http_responses ADD COLUMN remote_addr TEXT;
|
||||
ALTER TABLE http_responses ADD COLUMN version TEXT;
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::fs;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
@@ -7,13 +7,13 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use base64::Engine;
|
||||
use http::header::{ACCEPT, USER_AGENT};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method};
|
||||
use http::header::{ACCEPT, USER_AGENT};
|
||||
use log::{error, info, warn};
|
||||
use reqwest::redirect::Policy;
|
||||
use reqwest::{multipart, Url};
|
||||
use sqlx::types::{Json, JsonValue};
|
||||
use reqwest::redirect::Policy;
|
||||
use sqlx::{Pool, Sqlite};
|
||||
use sqlx::types::{Json, JsonValue};
|
||||
use tauri::{AppHandle, Wry};
|
||||
|
||||
use crate::{emit_side_effect, models, render, response_err};
|
||||
@@ -27,7 +27,6 @@ pub async fn send_http_request(
|
||||
pool: &Pool<Sqlite>,
|
||||
download_path: Option<PathBuf>,
|
||||
) -> Result<models::HttpResponse, String> {
|
||||
let start = std::time::Instant::now();
|
||||
let environment_ref = environment.as_ref();
|
||||
let workspace = models::get_workspace(&request.workspace_id, pool)
|
||||
.await
|
||||
@@ -298,11 +297,13 @@ pub async fn send_http_request(
|
||||
}
|
||||
};
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let raw_response = client.execute(sendable_req).await;
|
||||
|
||||
match raw_response {
|
||||
Ok(v) => {
|
||||
let mut response = response.clone();
|
||||
response.elapsed_headers = start.elapsed().as_millis() as i64;
|
||||
let response_headers = v.headers().clone();
|
||||
response.status = v.status().as_u16() as i64;
|
||||
response.status_reason = v.status().canonical_reason().map(|s| s.to_string());
|
||||
@@ -316,8 +317,25 @@ pub async fn send_http_request(
|
||||
.collect(),
|
||||
);
|
||||
response.url = v.url().to_string();
|
||||
response.remote_addr = v.remote_addr().map(|a| a.to_string());
|
||||
response.version = match v.version() {
|
||||
http::Version::HTTP_09 => Some("HTTP/0.9".to_string()),
|
||||
http::Version::HTTP_10 => Some("HTTP/1.0".to_string()),
|
||||
http::Version::HTTP_11 => Some("HTTP/1.1".to_string()),
|
||||
http::Version::HTTP_2 => Some("HTTP/2".to_string()),
|
||||
http::Version::HTTP_3 => Some("HTTP/3".to_string()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let content_length = v.content_length();
|
||||
let body_bytes = v.bytes().await.expect("Failed to get body").to_vec();
|
||||
response.content_length = Some(body_bytes.len() as i64);
|
||||
response.elapsed = start.elapsed().as_millis() as i64;
|
||||
|
||||
// Use content length if available, otherwise use body length
|
||||
response.content_length = match content_length {
|
||||
Some(l) => Some(l as i64),
|
||||
None => Some(body_bytes.len() as i64),
|
||||
};
|
||||
|
||||
{
|
||||
// Write body to FS
|
||||
@@ -344,7 +362,6 @@ pub async fn send_http_request(
|
||||
);
|
||||
}
|
||||
|
||||
response.elapsed = start.elapsed().as_millis() as i64;
|
||||
response = models::update_response_if_id(&response, pool)
|
||||
.await
|
||||
.expect("Failed to update response");
|
||||
|
||||
@@ -10,7 +10,7 @@ extern crate objc;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::env::current_dir;
|
||||
use std::fs::{create_dir_all, File, read_to_string};
|
||||
use std::fs::{create_dir_all, read_to_string, File};
|
||||
use std::process::exit;
|
||||
|
||||
use fern::colors::ColoredLevelConfig;
|
||||
@@ -18,13 +18,13 @@ use log::{debug, error, info, warn};
|
||||
use rand::random;
|
||||
use serde::Serialize;
|
||||
use serde_json::{json, Value};
|
||||
use sqlx::{Pool, Sqlite, SqlitePool};
|
||||
use sqlx::migrate::Migrator;
|
||||
use sqlx::types::Json;
|
||||
use tauri::{AppHandle, RunEvent, State, Window, WindowUrl, Wry};
|
||||
use tauri::{Manager, WindowEvent};
|
||||
use sqlx::{Pool, Sqlite, SqlitePool};
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::TitleBarStyle;
|
||||
use tauri::{AppHandle, RunEvent, State, Window, WindowUrl, Wry};
|
||||
use tauri::{Manager, WindowEvent};
|
||||
use tauri_plugin_log::{fern, LogTarget};
|
||||
use tauri_plugin_window_state::{StateFlags, WindowExt};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -292,9 +292,22 @@ async fn send_request(
|
||||
None => None,
|
||||
};
|
||||
|
||||
let response = models::create_response(&request.id, 0, "", 0, None, None, None, vec![], pool)
|
||||
.await
|
||||
.expect("Failed to create response");
|
||||
let response = models::create_response(
|
||||
&request.id,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
0,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
pool,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create response");
|
||||
|
||||
let download_path = if let Some(p) = download_dir {
|
||||
Some(std::path::Path::new(p).to_path_buf())
|
||||
|
||||
@@ -171,7 +171,10 @@ pub struct HttpResponse {
|
||||
pub error: Option<String>,
|
||||
pub url: String,
|
||||
pub content_length: Option<i64>,
|
||||
pub version: Option<String>,
|
||||
pub elapsed: i64,
|
||||
pub elapsed_headers: i64,
|
||||
pub remote_addr: Option<String>,
|
||||
pub status: i64,
|
||||
pub status_reason: Option<String>,
|
||||
pub body_path: Option<String>,
|
||||
@@ -851,15 +854,19 @@ pub async fn delete_request(id: &str, pool: &Pool<Sqlite>) -> Result<HttpRequest
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn create_response(
|
||||
request_id: &str,
|
||||
elapsed: i64,
|
||||
elapsed_headers: i64,
|
||||
url: &str,
|
||||
status: i64,
|
||||
status_reason: Option<&str>,
|
||||
content_length: Option<i64>,
|
||||
body_path: Option<&str>,
|
||||
headers: Vec<HttpResponseHeader>,
|
||||
version: Option<&str>,
|
||||
remote_addr: Option<&str>,
|
||||
pool: &Pool<Sqlite>,
|
||||
) -> Result<HttpResponse, sqlx::Error> {
|
||||
let req = get_request(request_id, pool).await?;
|
||||
@@ -872,25 +879,31 @@ pub async fn create_response(
|
||||
request_id,
|
||||
workspace_id,
|
||||
elapsed,
|
||||
elapsed_headers,
|
||||
url,
|
||||
status,
|
||||
status_reason,
|
||||
content_length,
|
||||
body_path,
|
||||
headers
|
||||
headers,
|
||||
version,
|
||||
remote_addr
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
"#,
|
||||
id,
|
||||
request_id,
|
||||
req.workspace_id,
|
||||
elapsed,
|
||||
elapsed_headers,
|
||||
url,
|
||||
status,
|
||||
status_reason,
|
||||
content_length,
|
||||
body_path,
|
||||
headers_json,
|
||||
version,
|
||||
remote_addr,
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
@@ -975,6 +988,7 @@ pub async fn update_response(
|
||||
r#"
|
||||
UPDATE http_responses SET (
|
||||
elapsed,
|
||||
elapsed_headers,
|
||||
url,
|
||||
status,
|
||||
status_reason,
|
||||
@@ -982,10 +996,13 @@ pub async fn update_response(
|
||||
body_path,
|
||||
error,
|
||||
headers,
|
||||
version,
|
||||
remote_addr,
|
||||
updated_at
|
||||
) = (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) WHERE id = ?;
|
||||
) = (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) WHERE id = ?;
|
||||
"#,
|
||||
response.elapsed,
|
||||
response.elapsed_headers,
|
||||
response.url,
|
||||
response.status,
|
||||
response.status_reason,
|
||||
@@ -993,6 +1010,8 @@ pub async fn update_response(
|
||||
response.body_path,
|
||||
response.error,
|
||||
headers_json,
|
||||
response.version,
|
||||
response.remote_addr,
|
||||
response.id,
|
||||
)
|
||||
.execute(pool)
|
||||
@@ -1004,8 +1023,10 @@ pub async fn get_response(id: &str, pool: &Pool<Sqlite>) -> Result<HttpResponse,
|
||||
sqlx::query_as!(
|
||||
HttpResponse,
|
||||
r#"
|
||||
SELECT id, model, workspace_id, request_id, updated_at, created_at, url,
|
||||
status, status_reason, content_length, body_path, elapsed, error,
|
||||
SELECT
|
||||
id, model, workspace_id, request_id, updated_at, created_at, url, status,
|
||||
status_reason, content_length, body_path, elapsed, elapsed_headers, error,
|
||||
version, remote_addr,
|
||||
headers AS "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>"
|
||||
FROM http_responses
|
||||
WHERE id = ?
|
||||
@@ -1021,15 +1042,14 @@ pub async fn find_responses(
|
||||
limit: Option<i64>,
|
||||
pool: &Pool<Sqlite>,
|
||||
) -> Result<Vec<HttpResponse>, sqlx::Error> {
|
||||
let limit_unwrapped = match limit {
|
||||
Some(l) => l,
|
||||
None => i64::MAX,
|
||||
};
|
||||
let limit_unwrapped = limit.unwrap_or_else(|| i64::MAX);
|
||||
sqlx::query_as!(
|
||||
HttpResponse,
|
||||
r#"
|
||||
SELECT id, model, workspace_id, request_id, updated_at, created_at, url,
|
||||
status, status_reason, content_length, body_path, elapsed, error,
|
||||
SELECT
|
||||
id, model, workspace_id, request_id, updated_at, created_at, url, status,
|
||||
status_reason, content_length, body_path, elapsed, elapsed_headers, error,
|
||||
version, remote_addr,
|
||||
headers AS "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>"
|
||||
FROM http_responses
|
||||
WHERE request_id = ?
|
||||
@@ -1050,8 +1070,10 @@ pub async fn find_responses_by_workspace_id(
|
||||
sqlx::query_as!(
|
||||
HttpResponse,
|
||||
r#"
|
||||
SELECT id, model, workspace_id, request_id, updated_at, created_at, url,
|
||||
status, status_reason, content_length, body_path, elapsed, error,
|
||||
SELECT
|
||||
id, model, workspace_id, request_id, updated_at, created_at, url, status,
|
||||
status_reason, content_length, body_path, elapsed, elapsed_headers, error,
|
||||
version, remote_addr,
|
||||
headers AS "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>"
|
||||
FROM http_responses
|
||||
WHERE workspace_id = ?
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
import classNames from 'classnames';
|
||||
import type { HttpResponse } from '../lib/models';
|
||||
import { Separator } from './core/Separator';
|
||||
import { HStack } from './core/Stacks';
|
||||
|
||||
interface Props {
|
||||
headers: HttpResponse['headers'];
|
||||
response: HttpResponse;
|
||||
}
|
||||
|
||||
export function ResponseHeaders({ headers }: Props) {
|
||||
export function ResponseHeaders({ response }: Props) {
|
||||
return (
|
||||
<dl className="text-xs w-full h-full font-mono overflow-auto">
|
||||
{headers.map((h, i) => {
|
||||
return (
|
||||
<HStack
|
||||
space={3}
|
||||
key={i}
|
||||
className={classNames(i > 0 ? 'border-t border-highlightSecondary py-1' : 'pb-1')}
|
||||
>
|
||||
<dd className="w-1/3 text-violet-600 select-text cursor-text">{h.name}</dd>
|
||||
<dt className="w-2/3 select-text cursor-text break-all">{h.value}</dt>
|
||||
</HStack>
|
||||
);
|
||||
})}
|
||||
</dl>
|
||||
<div className="overflow-auto h-full pb-4">
|
||||
<dl className="text-xs w-full font-mono flex flex-col">
|
||||
{response.headers.map((h, i) => (
|
||||
<Row key={i} label={h.name} value={h.value} labelClassName="!text-violet-600" />
|
||||
))}
|
||||
</dl>
|
||||
<Separator className="my-4">Other Info</Separator>
|
||||
<dl className="text-xs w-full font-mono divide-highlightSecondary">
|
||||
<Row label="Version" value={response.version} />
|
||||
<Row label="Remote Address" value={response.remoteAddr} />
|
||||
<Row label="Status" value={response.status} />
|
||||
<Row label="Reason" value={response.statusReason} />
|
||||
<Row label="URL" value={response.url} />
|
||||
</dl>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Row({
|
||||
label,
|
||||
value,
|
||||
labelClassName,
|
||||
}: {
|
||||
label: string;
|
||||
value: string | number;
|
||||
labelClassName?: string;
|
||||
}) {
|
||||
return (
|
||||
<HStack space={3} className="py-0.5">
|
||||
<dd className={classNames(labelClassName, 'w-1/3 text-gray-700 select-text cursor-text')}>
|
||||
{label}
|
||||
</dd>
|
||||
<dt className="w-2/3 select-text cursor-text break-all">{value}</dt>
|
||||
</HStack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,10 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
||||
{activeResponse.elapsed > 0 && (
|
||||
<>
|
||||
<span>•</span>
|
||||
<DurationTag millis={activeResponse.elapsed} />
|
||||
<DurationTag
|
||||
headers={activeResponse.elapsedHeaders}
|
||||
total={activeResponse.elapsed}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{!!activeResponse.contentLength && (
|
||||
@@ -160,7 +163,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
||||
tabListClassName="mt-1.5"
|
||||
>
|
||||
<TabContent value="headers">
|
||||
<ResponseHeaders headers={activeResponse?.headers ?? []} />
|
||||
<ResponseHeaders response={activeResponse} />
|
||||
</TabContent>
|
||||
<TabContent value="body">
|
||||
{!activeResponse.contentLength ? (
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
interface Props {
|
||||
millis: number;
|
||||
total: number;
|
||||
headers: number;
|
||||
}
|
||||
|
||||
export function DurationTag({ millis }: Props) {
|
||||
export function DurationTag({ total, headers }: Props) {
|
||||
return (
|
||||
<span title={`HEADER: ${formatMillis(headers)}\nTOTAL: ${formatMillis(total)}`}>
|
||||
{formatMillis(total)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function formatMillis(millis: number) {
|
||||
let num;
|
||||
let unit;
|
||||
|
||||
@@ -17,9 +26,5 @@ export function DurationTag({ millis }: Props) {
|
||||
unit = 'ms';
|
||||
}
|
||||
|
||||
return (
|
||||
<span title={`${millis} milliseconds`}>
|
||||
{Math.round(num * 10) / 10} {unit}
|
||||
</span>
|
||||
);
|
||||
return `${Math.round(num * 10) / 10} ${unit}`;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export function Separator({
|
||||
}: Props) {
|
||||
return (
|
||||
<div role="separator" className={classNames(className, 'flex items-center')}>
|
||||
{children && <div className="text-xs text-gray-500 mx-2 whitespace-nowrap">{children}</div>}
|
||||
{children && <div className="text-xs text-gray-500 mr-2 whitespace-nowrap">{children}</div>}
|
||||
<div
|
||||
className={classNames(
|
||||
variant === 'primary' && 'bg-highlight',
|
||||
|
||||
@@ -133,7 +133,10 @@ export interface HttpResponse extends BaseModel {
|
||||
readonly error: string;
|
||||
readonly status: number;
|
||||
readonly elapsed: number;
|
||||
readonly elapsedHeaders: number;
|
||||
readonly statusReason: string;
|
||||
readonly version: string;
|
||||
readonly remoteAddr: string;
|
||||
readonly url: string;
|
||||
readonly headers: HttpHeader[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user