Restructured response builder to give YAML or JSON when SSZ is not available, not just JSON.

This commit is contained in:
Luke Anderson
2019-09-13 20:42:56 +10:00
parent 1dd86baf1a
commit f48311900e
8 changed files with 76 additions and 48 deletions

View File

@@ -8,6 +8,7 @@ pub enum Encoding {
JSON,
SSZ,
YAML,
TEXT,
}
pub struct ResponseBuilder {
@@ -15,22 +16,55 @@ pub struct ResponseBuilder {
}
impl ResponseBuilder {
pub fn new(req: &Request<Body>) -> Self {
let encoding = match req.headers().get(header::CONTENT_TYPE) {
Some(h) if h == "application/ssz" => Encoding::SSZ,
Some(h) if h == "application/yaml" => Encoding::YAML,
pub fn new(req: &Request<Body>) -> Result<Self, ApiError> {
let content_header = req
.headers()
.get(header::CONTENT_TYPE)
.map_or(Ok(""), |h| h.to_str())
.map_err(|e| {
ApiError::InvalidQueryParams(format!(
"The content-type header contains invalid characters: {:?}",
e
))
})
.map(|h| String::from(h))?;
let encoding = match content_header {
ref h if h.starts_with("application/ssz") => Encoding::SSZ,
ref h if h.starts_with("application/yaml") => Encoding::YAML,
ref h if h.starts_with("text/plain") => Encoding::TEXT,
_ => Encoding::JSON,
};
Self { encoding }
Ok(Self { encoding })
}
pub fn body<T: Serialize + Encode>(self, item: &T) -> ApiResult {
match self.encoding {
Encoding::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<T: Serialize>(self, item: &T) -> ApiResult {
let (body, content_type) = match self.encoding {
Encoding::JSON => {
return self.body_json(item);
Encoding::JSON => (
Body::from(serde_json::to_string(&item).map_err(|e| {
ApiError::ServerError(format!(
"Unable to serialize response body as JSON: {:?}",
e
))
})?),
"application/json",
),
Encoding::SSZ => {
return Err(ApiError::UnsupportedType(
"Response cannot be encoded as SSZ.".into(),
));
}
Encoding::SSZ => (Body::from(item.as_ssz_bytes()), "application/ssz"),
Encoding::YAML => (
Body::from(serde_yaml::to_string(&item).map_err(|e| {
ApiError::ServerError(format!(
@@ -38,8 +72,13 @@ impl ResponseBuilder {
e
))
})?),
"application/ssz",
"application/yaml",
),
Encoding::TEXT => {
return Err(ApiError::UnsupportedType(
"Response cannot be encoded as plain text.".into(),
));
}
};
Response::builder()
@@ -49,19 +88,6 @@ impl ResponseBuilder {
.map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e)))
}
pub fn body_json<T: Serialize>(self, item: &T) -> ApiResult {
Response::builder()
.status(StatusCode::OK)
.header("content-type", "application/json")
.body(Body::from(serde_json::to_string(&item).map_err(|e| {
ApiError::ServerError(format!(
"Unable to serialize response body as JSON: {:?}",
e
))
})?))
.map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e)))
}
pub fn body_text(self, text: String) -> ApiResult {
Response::builder()
.status(StatusCode::OK)