use std::collections::BTreeMap;
use http::{
HeaderMap,
HeaderValue,
};
use crate::Sensitivity;
use super::HttpRedactor;
use crate::http::internal::BoundedLogWriter;
pub(super) fn group_values(
headers: &HeaderMap,
) -> BTreeMap<&str, Vec<&HeaderValue>> {
let mut values = BTreeMap::<&str, Vec<&HeaderValue>>::new();
for (name, value) in headers {
values.entry(name.as_str()).or_default().push(value);
}
values
}
impl HttpRedactor {
pub(super) fn headers_fit_input_budget(&self, headers: &HeaderMap) -> bool {
let input_limit =
self.policy().limits().diagnostic_event().max_input_bytes();
let mut input_bytes = 0_usize;
for (name, value) in headers {
input_bytes = input_bytes
.saturating_add(name.as_str().len())
.saturating_add(value.as_bytes().len());
if input_bytes > input_limit {
return false;
}
}
true
}
pub(super) fn write_grouped_headers(
&self,
writer: &mut BoundedLogWriter,
values: BTreeMap<&str, Vec<&HeaderValue>>,
) {
for (name_index, (name, header_values)) in
values.into_iter().enumerate()
{
if name_index > 0 {
let _ = writer.write_str("\n");
}
let _ = writer.write_str(name);
let _ = writer.write_str(": [");
self.write_header_values(writer, name, &header_values);
if writer.is_full() {
break;
}
let _ = writer.write_str("]");
}
}
fn write_header_values(
&self,
writer: &mut BoundedLogWriter,
name: &str,
values: &[&HeaderValue],
) {
for (value_index, value) in values.iter().enumerate() {
if writer.is_full() {
break;
}
if value_index > 0 {
let _ = writer.write_str(", ");
}
let rendered = value.to_str().unwrap_or("<non-utf8>");
let remaining = writer.remaining_bytes();
if value.is_sensitive() {
let redacted = self.header_field_redactor().mask_bounded(
Sensitivity::Secret,
rendered,
remaining,
);
let _ = writer.write_str(redacted.as_ref());
} else {
let redacted = self
.header_field_redactor()
.redact_bounded(name, rendered, remaining);
let _ = writer.write_str(redacted.as_str());
}
}
}
}