Skip to content

Commit e15d30e

Browse files
committed
add logging
1 parent 982f504 commit e15d30e

File tree

4 files changed

+101
-8
lines changed

4 files changed

+101
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ethereum_ssz_derive = "0.7"
2323
flate2 = "1.0"
2424
futures = "0.3.30"
2525
http = "1"
26+
mediatype = "0.19.13"
2627
reqwest = { version = "0.12.5", features = ["json"] }
2728
serde = { version = "1.0", features = ["derive"] }
2829
serde_json = { version = "1", features = ["raw_value"] }

builder-server/src/server.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::str::FromStr;
2+
13
use axum::{
24
body::Body,
35
extract::{Path, State},
@@ -11,9 +13,13 @@ use builder_api_types::{
1113
SignedValidatorRegistrationData, Slot,
1214
};
1315
use ethereum_apis_common::{
14-
build_response, build_response_with_headers, ContentType, JsonOrSszWithFork,
16+
build_response, build_response_with_headers, Accept, ContentType, JsonOrSszWithFork,
17+
};
18+
use http::{
19+
header::{ACCEPT, CONTENT_TYPE},
20+
HeaderMap,
1521
};
16-
use http::{header::CONTENT_TYPE, HeaderMap};
22+
use tracing::info;
1723

1824
use crate::builder::Builder;
1925

@@ -89,12 +95,21 @@ where
8995
I: AsRef<A> + Send + Sync,
9096
A: Builder<E>,
9197
{
92-
let content_type_header = headers.get(CONTENT_TYPE);
93-
let content_type = content_type_header.and_then(|value| value.to_str().ok());
94-
let content_type = match content_type {
95-
Some("application/octet-stream") => ContentType::Ssz,
96-
_ => ContentType::Json,
98+
let content_type_header = headers.get(ACCEPT);
99+
let content_type_str = content_type_header
100+
.and_then(|value| value.to_str().ok())
101+
.unwrap_or("application/json");
102+
let content_type = match Accept::from_str(content_type_str) {
103+
Ok(Accept::Ssz) => {
104+
info!("REQUESTED SSZ");
105+
ContentType::Ssz
106+
},
107+
_ => {
108+
info!("REQUESTED JSON");
109+
ContentType::Json
110+
},
97111
};
112+
98113
let res = api_impl
99114
.as_ref()
100115
.get_header(slot, parent_hash, pubkey)

common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ethereum_ssz.workspace = true
1111
flate2.workspace = true
1212
futures.workspace = true
1313
http.workspace = true
14+
mediatype.workspace = true
1415
serde.workspace = true
1516
serde_json.workspace = true
1617
tokio.workspace = true

common/src/lib.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use bytes::Bytes;
1212
use flate2::read::GzDecoder;
1313
use http::header::CONTENT_ENCODING;
1414
use http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
15+
use mediatype::{names, MediaType, MediaTypeList};
1516
use serde::{Deserialize, Serialize};
1617
use ssz::Encode;
17-
use std::{io::Read, str::FromStr};
18+
use std::{fmt, io::Read, str::FromStr};
1819
use tracing::error;
1920

2021
pub const CONSENSUS_VERSION_HEADER: &str = "Eth-Consensus-Version";
@@ -464,3 +465,78 @@ where
464465
Ok(Self(result))
465466
}
466467
}
468+
469+
#[derive(Debug, Clone, Copy, PartialEq)]
470+
pub enum Accept {
471+
Json,
472+
Ssz,
473+
Any,
474+
}
475+
476+
impl fmt::Display for Accept {
477+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478+
match self {
479+
Accept::Ssz => write!(f, "application/octet-stream"),
480+
Accept::Json => write!(f, "application/json"),
481+
Accept::Any => write!(f, "*/*"),
482+
}
483+
}
484+
}
485+
486+
impl FromStr for Accept {
487+
type Err = String;
488+
489+
fn from_str(s: &str) -> Result<Self, Self::Err> {
490+
let media_type_list = MediaTypeList::new(s);
491+
492+
// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
493+
// find the highest q-factor supported accept type
494+
let mut highest_q = 0_u16;
495+
let mut accept_type = None;
496+
497+
const APPLICATION: &str = names::APPLICATION.as_str();
498+
const OCTET_STREAM: &str = names::OCTET_STREAM.as_str();
499+
const JSON: &str = names::JSON.as_str();
500+
const STAR: &str = names::_STAR.as_str();
501+
const Q: &str = names::Q.as_str();
502+
503+
media_type_list.into_iter().for_each(|item| {
504+
if let Ok(MediaType {
505+
ty,
506+
subty,
507+
suffix: _,
508+
params,
509+
}) = item
510+
{
511+
let q_accept = match (ty.as_str(), subty.as_str()) {
512+
(APPLICATION, OCTET_STREAM) => Some(Accept::Ssz),
513+
(APPLICATION, JSON) => Some(Accept::Json),
514+
(STAR, STAR) => Some(Accept::Any),
515+
_ => None,
516+
}
517+
.map(|item_accept_type| {
518+
let q_val = params
519+
.iter()
520+
.find_map(|(n, v)| match n.as_str() {
521+
Q => {
522+
Some((v.as_str().parse::<f32>().unwrap_or(0_f32) * 1000_f32) as u16)
523+
}
524+
_ => None,
525+
})
526+
.or(Some(1000_u16));
527+
528+
(q_val.unwrap(), item_accept_type)
529+
});
530+
531+
match q_accept {
532+
Some((q, accept)) if q > highest_q => {
533+
highest_q = q;
534+
accept_type = Some(accept);
535+
}
536+
_ => (),
537+
}
538+
}
539+
});
540+
accept_type.ok_or_else(|| "accept header is not supported".to_string())
541+
}
542+
}

0 commit comments

Comments
 (0)