Fix http header accept parsing problem (#3185)
## Issue Addressed Which issue # does this PR address? #3114 ## Proposed Changes 1. introduce `mime` package 2. Parse `Accept` field in the header with `mime` ## Additional Info Please provide any additional information. For example, future considerations or information useful for reviewers.
This commit is contained in:
parent
def9bc660e
commit
0428018cc1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1586,6 +1586,7 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"libsecp256k1",
|
"libsecp256k1",
|
||||||
"lighthouse_network",
|
"lighthouse_network",
|
||||||
|
"mime",
|
||||||
"procinfo",
|
"procinfo",
|
||||||
"proto_array",
|
"proto_array",
|
||||||
"psutil",
|
"psutil",
|
||||||
|
@ -26,6 +26,7 @@ futures-util = "0.3.8"
|
|||||||
futures = "0.3.8"
|
futures = "0.3.8"
|
||||||
store = { path = "../../beacon_node/store", optional = true }
|
store = { path = "../../beacon_node/store", optional = true }
|
||||||
slashing_protection = { path = "../../validator_client/slashing_protection", optional = true }
|
slashing_protection = { path = "../../validator_client/slashing_protection", optional = true }
|
||||||
|
mime = "0.3.16"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
psutil = { version = "3.2.2", optional = true }
|
psutil = { version = "3.2.2", optional = true }
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
use crate::Error as ServerError;
|
use crate::Error as ServerError;
|
||||||
use lighthouse_network::{ConnectionDirection, Enr, Multiaddr, PeerConnectionStatus};
|
use lighthouse_network::{ConnectionDirection, Enr, Multiaddr, PeerConnectionStatus};
|
||||||
|
use mime::{Mime, APPLICATION, JSON, OCTET_STREAM, STAR};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::cmp::Reverse;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::{from_utf8, FromStr};
|
use std::str::{from_utf8, FromStr};
|
||||||
@ -1008,15 +1010,37 @@ impl FromStr for Accept {
|
|||||||
type Err = String;
|
type Err = String;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
let mut mimes = parse_accept(s)?;
|
||||||
"application/octet-stream" => Ok(Accept::Ssz),
|
|
||||||
"application/json" => Ok(Accept::Json),
|
// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||||
"*/*" => Ok(Accept::Any),
|
// find the highest q-factor supported accept type
|
||||||
_ => Err("accept header cannot be parsed.".to_string()),
|
mimes.sort_by_key(|m| {
|
||||||
}
|
Reverse(m.get_param("q").map_or(1000_u16, |n| {
|
||||||
|
(n.as_ref().parse::<f32>().unwrap_or(0_f32) * 1000_f32) as u16
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
mimes
|
||||||
|
.into_iter()
|
||||||
|
.find_map(|m| match (m.type_(), m.subtype()) {
|
||||||
|
(APPLICATION, OCTET_STREAM) => Some(Accept::Ssz),
|
||||||
|
(APPLICATION, JSON) => Some(Accept::Json),
|
||||||
|
(STAR, STAR) => Some(Accept::Any),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.ok_or_else(|| "accept header is not supported".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_accept(accept: &str) -> Result<Vec<Mime>, String> {
|
||||||
|
accept
|
||||||
|
.split(',')
|
||||||
|
.map(|part| {
|
||||||
|
part.parse()
|
||||||
|
.map_err(|e| format!("error parsing Accept header: {}", e))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct LivenessRequestData {
|
pub struct LivenessRequestData {
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
@ -1045,4 +1069,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_accept_header_content() {
|
||||||
|
assert_eq!(
|
||||||
|
Accept::from_str("application/json; charset=utf-8").unwrap(),
|
||||||
|
Accept::Json
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Accept::from_str("text/plain,application/octet-stream;q=0.3,application/json;q=0.9")
|
||||||
|
.unwrap(),
|
||||||
|
Accept::Json
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Accept::from_str("text/plain"),
|
||||||
|
Err("accept header is not supported".to_string())
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user