Commit 9f9bd43
Show response headers
Changed files (3)
Diff
@@ -64,9 +64,16 @@ struct PostResponse { status: u16, status_text: String, url: String,+ headers: Vec<ResponseHeader>, body: String, } +#[derive(Serialize)]+struct ResponseHeader {+ name: String,+ value: String,+}+ fn projects_file_path(app: &AppHandle) -> Result<PathBuf, String> { let config_dir = app.path().app_config_dir().map_err(|error| { format!("Could not find the application configuration directory: {error}")@@ -409,6 +416,14 @@ async fn send_request( .canonical_reason() .unwrap_or("Unknown status") .to_owned();+ let headers = response+ .headers()+ .iter()+ .map(|(name, value)| ResponseHeader {+ name: name.as_str().to_owned(),+ value: String::from_utf8_lossy(value.as_bytes()).into_owned(),+ })+ .collect(); let body = response .text() .await@@ -419,6 +434,7 @@ async fn send_request( status: status.as_u16(), status_text, url: response_url,+ headers, body, }) }@@ -54,9 +54,16 @@ struct PostResponse { status: u16, status_text: String, url: String,+ headers: Vec<ResponseHeader>, body: String, } +#[derive(Deserialize)]+struct ResponseHeader {+ name: String,+ value: String,+}+ #[component("app-root")] struct App { #[attribute]@@ -303,6 +310,8 @@ impl RestCallSetupComponent { <p id="request-status" class="request-status" role="status" aria-live="polite"></p> <p id="request-url" class="request-url"></p> <section id="request-response" class="request-response" aria-label="Response" hidden>+ <button id="response-headers-toggle" class="button-secondary response-headers-toggle" type="button" onclick="toggleResponseHeaders()" aria-controls="response-headers" aria-expanded="false">Show response headers</button>+ <div id="response-headers" class="response-headers" hidden></div> <pre id="request-result"></pre> </section> </main>@@ -1136,9 +1145,51 @@ fn clear_request_result() { let _ = response.set_attribute("class", "request-response request-response-empty"); let _ = response.set_attribute("aria-hidden", "true"); }+ reset_response_headers(); try_inner_text("#request-result", ""); } +fn format_response_headers(headers: &[ResponseHeader]) -> String {+ headers+ .iter()+ .map(|header| format!("{}: {}", header.name, header.value))+ .collect::<Vec<_>>()+ .join("\n")+}++fn reset_response_headers() {+ if let Some(headers) = get_element("#response-headers") {+ let _ = headers.set_attribute("hidden", "");+ headers.set_text_content(None);+ }+ if let Some(toggle) = get_element("#response-headers-toggle") {+ let _ = toggle.set_attribute("aria-expanded", "false");+ toggle.set_text_content(Some("Show response headers"));+ }+}++#[callback(toggleResponseHeaders)]+fn toggle_response_headers() {+ let Some(headers) = get_element("#response-headers") else {+ return;+ };+ let expanded = headers.has_attribute("hidden");+ if expanded {+ let _ = headers.remove_attribute("hidden");+ } else {+ let _ = headers.set_attribute("hidden", "");+ }++ if let Some(toggle) = get_element("#response-headers-toggle") {+ let _ = toggle.set_attribute("aria-expanded", if expanded { "true" } else { "false" });+ toggle.set_text_content(Some(if expanded {+ "Hide response headers"+ } else {+ "Show response headers"+ }));+ }+}+ fn format_response_body(body: &str) -> String { serde_json::from_str::<serde_json::Value>(body) .and_then(|value| serde_json::to_string_pretty(&value))@@ -1151,17 +1202,17 @@ fn render_request_response(response: PostResponse) { &format!("{} {}", response.method, response.url), ); - if response.body.trim().is_empty() {- clear_request_result();- return;- }- if let Some(response_container) = get_element("#request-response") { let _ = response_container.remove_attribute("hidden"); let _ = response_container.set_attribute("class", "request-response"); let _ = response_container.remove_attribute("aria-hidden"); } + reset_response_headers();+ try_inner_text(+ "#response-headers",+ &format_response_headers(&response.headers),+ ); try_inner_text("#request-result", &format_response_body(&response.body)); if let Some(result) = get_element("#request-result") { let _ = result.remove_attribute("style");@@ -432,6 +432,28 @@ button:focus-visible { visibility: hidden; } +.response-headers-toggle {+ margin: 14px 14px 0;+}++.response-headers {+ margin: 12px 14px 0;+ padding: 12px;+ color: #334155;+ background: #ffffff;+ border: 1px solid #cbd5e1;+ border-radius: 7px;+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;+ font-size: 0.875rem;+ line-height: 1.5;+ white-space: pre-wrap;+ overflow-wrap: anywhere;+}++.response-headers[hidden] {+ display: none;+}+ #request-result { box-sizing: border-box; margin: 0;@@ -545,6 +567,12 @@ button:focus-visible { border-color: #334155; } + .response-headers {+ color: #cbd5e1;+ background: #1f2937;+ border-color: #334155;+ }+ button { background: #1d4ed8; border-color: #1d4ed8;