use super::{ApiError, ApiResult}; use crate::config::ApiEncodingFormat; use http::header; use hyper::{Body, Request, Response, StatusCode}; use serde::Serialize; use ssz::Encode; pub struct ResponseBuilder { encoding: ApiEncodingFormat, } impl ResponseBuilder { pub fn new(req: &Request) -> Result { let accept_header: String = req .headers() .get(header::ACCEPT) .map_or(Ok(""), |h| h.to_str()) .map_err(|e| { ApiError::BadRequest(format!( "The Accept header contains invalid characters: {:?}", e )) }) .map(String::from)?; // JSON is our default encoding, unless something else is requested. let encoding = ApiEncodingFormat::from(accept_header.as_str()); Ok(Self { encoding }) } pub fn body(self, item: &T) -> ApiResult { match self.encoding { ApiEncodingFormat::SSZ => Response::builder() .status(StatusCode::OK) .header("content-type", "application/ssz") .body(Body::from(item.as_ssz_bytes())) .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))), _ => self.body_no_ssz(item), } } pub fn body_no_ssz(self, item: &T) -> ApiResult { let (body, content_type) = match self.encoding { ApiEncodingFormat::JSON => ( Body::from(serde_json::to_string(&item).map_err(|e| { ApiError::ServerError(format!( "Unable to serialize response body as JSON: {:?}", e )) })?), "application/json", ), ApiEncodingFormat::SSZ => { return Err(ApiError::UnsupportedType( "Response cannot be encoded as SSZ.".into(), )); } ApiEncodingFormat::YAML => ( Body::from(serde_yaml::to_string(&item).map_err(|e| { ApiError::ServerError(format!( "Unable to serialize response body as YAML: {:?}", e )) })?), "application/yaml", ), }; Response::builder() .status(StatusCode::OK) .header("content-type", content_type) .body(body) .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))) } pub fn body_text(self, text: String) -> ApiResult { Response::builder() .status(StatusCode::OK) .header("content-type", "text/plain; charset=utf-8") .body(Body::from(text)) .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))) } }