Repository navigation
Expand file tree
/
Copy pathfetch_with_meta.rs
More file actions
94 lines (82 loc) · 3.35 KB
/
Copy pathfetch_with_meta.rs
File metadata and controls
94 lines (82 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use opentelemetry_semantic_conventions::attribute as otel;
use tracing::Instrument;
use crate::webserver::{
database::sqlpage_functions::http_fetch_request::HttpFetchRequest,
http_request_info::RequestInfo,
};
use super::fetch::{decode_response, fetch_span, send_request};
pub(super) async fn fetch_with_meta(
request: &RequestInfo,
http_request: Option<HttpFetchRequest<'_>>,
) -> anyhow::Result<Option<String>> {
use serde::{Serializer, ser::SerializeMap};
let Some(http_request) = http_request else {
return Ok(None);
};
let fetch_span = fetch_span(&http_request);
async {
let response_result = send_request(request, &http_request)?.await;
let mut resp_str = Vec::new();
let mut encoder = serde_json::Serializer::new(&mut resp_str);
let mut obj = encoder.serialize_map(Some(3))?;
match response_result {
Ok(mut response) => {
let status = response.status();
tracing::Span::current()
.record(otel::HTTP_RESPONSE_STATUS_CODE, i64::from(status.as_u16()));
obj.serialize_entry("status", &status.as_u16())?;
let mut has_error = false;
if status.is_server_error() {
has_error = true;
obj.serialize_entry("error", &format!("Server error: {status}"))?;
}
let headers = response.headers();
let is_json = headers
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or_default()
.starts_with("application/json");
obj.serialize_entry(
"headers",
&headers
.iter()
.map(|(k, v)| (k.to_string(), v.to_str().unwrap_or_default()))
.collect::<std::collections::HashMap<_, _>>(),
)?;
match response.body().await {
Ok(body) => {
let body_bytes = body.to_vec();
let body_str =
decode_response(body_bytes, http_request.response_encoding.as_deref())?;
if is_json {
obj.serialize_entry(
"json_body",
&serde_json::value::RawValue::from_string(body_str)?,
)?;
} else {
obj.serialize_entry("body", &body_str)?;
}
}
Err(e) => {
log::warn!("Failed to read response body: {e}");
if !has_error {
obj.serialize_entry(
"error",
&format!("Failed to read response body: {e}"),
)?;
}
}
}
}
Err(e) => {
log::warn!("Request failed: {e}");
obj.serialize_entry("error", &format!("Request failed: {e}"))?;
}
}
obj.end()?;
let return_value = String::from_utf8(resp_str)?;
Ok(Some(return_value))
}
.instrument(fetch_span)
.await
}