use fluke_hpack::Decoder;
#[allow(dead_code)]
pub fn find_http2_authority(bytes: &[u8]) -> Option<String> {
let mut current = 0;
while current + 9 <= bytes.len() {
let length =
u32::from_be_bytes([0, bytes[current], bytes[current + 1], bytes[current + 2]])
as usize;
let frame_type = bytes[current + 3];
let _flags = bytes[current + 4];
let stream_id = u32::from_be_bytes([
0,
bytes[current + 5],
bytes[current + 6],
bytes[current + 7],
]) & 0x7fffffff;
current += 9; if frame_type == 0x1 {
if stream_id % 2 != 0 {
let header_block_fragment = &bytes[current..current + length];
if let Ok(headers) = decompress_hpack(header_block_fragment) {
for (name, value) in headers {
if name == ":authority" {
return Some(value);
}
}
} else {
tracing::trace!("failed to decode headers using hpack!");
return None;
}
}
}
current += length;
}
None
}
fn decompress_hpack(fragment: &[u8]) -> Result<Vec<(String, String)>, String> {
let mut decoder = Decoder::new();
match decoder.decode(fragment) {
Ok(headers) => Ok(headers
.into_iter()
.map(|(key, value)| {
let h = String::from_utf8(key).map_err(|e| format!("{e:?}"))?;
let v = String::from_utf8(value).map_err(|e| format!("{e:?}"))?;
Ok((h, v))
})
.collect::<Result<Vec<(String, String)>, String>>()?),
e => Err(format!("{e:?}")),
}
}
pub fn is_valid_http2_request(bytes: &[u8]) -> bool {
let http2_preface = b"PRI * HTTP/2.0"; let result = bytes.starts_with(http2_preface);
result
}