Skip to content

Commit

Permalink
handle non-ascii header values (#1785)
Browse files Browse the repository at this point in the history
Similar to #1781 there are other
places where we should handle non-ascii header values
  • Loading branch information
fredr authored Feb 26, 2025
1 parent e1128c7 commit 7e5d369
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 11 deletions.
24 changes: 18 additions & 6 deletions runtimes/core/src/api/reqauth/meta.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
use std::str::{self, FromStr};

use http::HeaderValue;

pub trait HeaderValueExt {
fn to_utf8_str(&self) -> Result<&str, std::str::Utf8Error>;
}

impl HeaderValueExt for HeaderValue {
// Some header values may contain utf8 characters (e.g authdata) so we use `str::from_utf8`
// rather than using `HeaderValues::to_str` which errors on non-visible ASCII characters.
fn to_utf8_str(&self) -> Result<&str, std::str::Utf8Error> {
std::str::from_utf8(self.as_bytes())
}
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub enum MetaKey {
TraceParent,
Expand Down Expand Up @@ -78,17 +92,15 @@ impl MetaMapMut for reqwest::header::HeaderMap {

impl MetaMap for axum::http::HeaderMap {
fn get_meta(&self, key: MetaKey) -> Option<&str> {
// Some meta values may contain utf8 characters (e.g authdata) so we use `str::from_utf8`
// rather than using `HeaderValues::to_str` which errors on non-visible ASCII characters.
self.get(key.header_key())
.and_then(|val| std::str::from_utf8(val.as_bytes()).ok())
.and_then(|val| val.to_utf8_str().ok())
}

fn meta_values<'a>(&'a self, key: MetaKey) -> Box<dyn Iterator<Item = &'a str> + 'a> {
Box::new(
self.get_all(key.header_key())
.iter()
.filter_map(|v| v.to_str().ok()),
.filter_map(|v| v.to_utf8_str().ok()),
)
}

Expand All @@ -113,15 +125,15 @@ impl MetaMap for pingora::http::RequestHeader {
fn get_meta(&self, key: MetaKey) -> Option<&str> {
self.headers
.get(key.header_key())
.and_then(|v| v.to_str().ok())
.and_then(|v| v.to_utf8_str().ok())
}

fn meta_values<'a>(&'a self, key: MetaKey) -> Box<dyn Iterator<Item = &'a str> + 'a> {
Box::new(
self.headers
.get_all(key.header_key())
.iter()
.filter_map(|v| v.to_str().ok()),
.filter_map(|v| v.to_utf8_str().ok()),
)
}

Expand Down
5 changes: 3 additions & 2 deletions runtimes/core/src/api/schema/header.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::api::reqauth::meta::HeaderValueExt;
use crate::api::schema::{JSONPayload, ParseResponse, ToOutgoingRequest, ToResponse};
use crate::api::{self, PValue, PValues};
use crate::api::{jsonschema, APIResult};
Expand Down Expand Up @@ -74,10 +75,10 @@ impl AsStr for &axum::http::header::HeaderName {
}

impl ToHeaderStr for &axum::http::header::HeaderValue {
type Error = axum::http::header::ToStrError;
type Error = std::str::Utf8Error;

fn to_str(&self) -> Result<&str, Self::Error> {
<axum::http::header::HeaderValue>::to_str(self)
<axum::http::header::HeaderValue>::to_utf8_str(self)
}
fn is_empty(&self) -> bool {
<axum::http::header::HeaderValue>::is_empty(self)
Expand Down
3 changes: 2 additions & 1 deletion runtimes/core/src/trace/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::sync::atomic::{AtomicU64, Ordering};

use crate::api::reqauth::meta::HeaderValueExt;
use crate::api::{self, PValue};
use crate::model::{LogField, LogFieldValue, Request, TraceEventId};
use crate::trace::eventbuf::EventBuffer;
Expand Down Expand Up @@ -888,7 +889,7 @@ impl EventBuffer {
self.uvarint(headers.len() as u64);
for (k, v) in headers.iter() {
self.str(k.as_str());
self.str(v.to_str().unwrap_or(""));
self.str(v.to_utf8_str().unwrap_or(""));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions runtimes/js/src/request_meta.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use chrono::{DateTime, SecondsFormat, Utc};
use napi_derive::napi;

use encore_runtime_core::model;
use encore_runtime_core::{api::reqauth::meta::HeaderValueExt, model};

use crate::pvalue::PVals;

Expand Down Expand Up @@ -149,7 +149,7 @@ fn serialize_headers(
let mut map = Map::with_capacity(headers.len());

for (k, v) in headers {
let Ok(v) = v.to_str() else {
let Ok(v) = v.to_utf8_str() else {
continue;
};

Expand Down

0 comments on commit 7e5d369

Please sign in to comment.