Skip to content

Commit

Permalink
exchange hyper features From<Template> for hyper::Body with TryFrom
Browse files Browse the repository at this point in the history
The previous implementation hid the error returned by render,
which made it impossible for callers to react to rendering errors.

While having a simple way to call into would be nice, there is not
way to have both implementations without adding any manual
specialization. Thus, the From impl is replaced by the TryFrom impl.
  • Loading branch information
valkum authored and djc committed Mar 3, 2023
1 parent c9613ff commit 4a7068d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 29 deletions.
12 changes: 5 additions & 7 deletions askama_derive/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,24 +450,22 @@ impl<'a> Generator<'a> {
buf.writeln("}")?;
buf.writeln("}")?;

// From<Template> for hyper::Body
// TryFrom<Template> for hyper::Body
buf.writeln(&format!(
"{} {{",
quote!(
impl #impl_generics ::core::convert::From<&#ident #orig_ty_generics>
impl #impl_generics ::core::convert::TryFrom<&#ident #orig_ty_generics>
for ::askama_hyper::hyper::Body
#where_clause
)
))?;
buf.writeln("type Error = ::askama::Error;")?;
buf.writeln("#[inline]")?;
buf.writeln(&format!(
"{} {{",
quote!(fn from(value: &#ident #orig_ty_generics) -> Self)
quote!(fn try_from(value: &#ident #orig_ty_generics) -> Result<Self, Self::Error>)
))?;
buf.writeln(
"::askama::Template::render(value).ok().map(Into::into)\
.unwrap_or_else(|| ::askama_hyper::hyper::Body::empty())",
)?;
buf.writeln("::askama::Template::render(value).map(Into::into)")?;
buf.writeln("}")?;
buf.writeln("}")
}
Expand Down
33 changes: 11 additions & 22 deletions askama_hyper/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ async fn hello_handler(req: Request<Body>) -> Result<Response<Body>, Infallible>
Ok(template.into())
}

async fn body_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
async fn try_body_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
let name = req.param("name").unwrap();
let template = &HelloTemplate { name: &name };
Ok(Builder::new().body(template.into()).unwrap())
Ok(Builder::new().body(template.try_into().unwrap()).unwrap())
}

fn router() -> Router<Body, Infallible> {
Router::builder()
.get("/hello/:name", hello_handler)
.get("/body/:name", body_handler)
.get("/try_body/:name", try_body_handler)
.build()
.unwrap()
}
Expand All @@ -43,15 +43,12 @@ async fn test_hyper() {
let server = Server::bind(&addr).serve(service);
let local_addr = server.local_addr();

let (tx1, rx1) = tokio::sync::oneshot::channel::<()>();
let (tx2, rx2) = tokio::sync::oneshot::channel::<()>();
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<()>();
let serve = async move {
let server = server.with_graceful_shutdown(async {
rx1.await.expect("Could not await signal to stop");
rx2.await.expect("Could not await signal to stop");
});
let server = server.with_graceful_shutdown(async { while rx.recv().await.is_some() {} });
server.await.expect("Could not serve");
};
let hello_tx = tx.clone();
let hello_query = async move {
let uri = format!("http://{local_addr}/hello/world")
.parse()
Expand All @@ -73,32 +70,24 @@ async fn test_hyper() {
let body = std::str::from_utf8(&body).expect("Body was not UTF-8");
assert_eq!(body, "Hello, world!");

tx1.send(()).unwrap();
hello_tx.send(()).unwrap();
};

let body_query = async move {
let uri = format!("http://{local_addr}/hello/world")
let try_body_query = async move {
let uri = format!("http://{local_addr}/try_body/world")
.parse()
.expect("Could not format URI");
let client = Client::new();

let res = client.get(uri).await.expect("Could not query client");
assert_eq!(res.status(), hyper::StatusCode::OK);

let content_type = res
.headers()
.get("content-type")
.expect("Response did not contain content-type header")
.to_str()
.expect("Content-type was not a UTF-8 string");
assert_eq!(content_type, mime::TEXT_HTML_UTF_8.to_string());

let body = to_bytes(res).await.expect("No body returned");
let body = std::str::from_utf8(&body).expect("Body was not UTF-8");
assert_eq!(body, "Hello, world!");

tx2.send(()).unwrap();
tx.send(()).unwrap();
};

tokio::join!(serve, body_query, hello_query);
tokio::join!(serve, try_body_query, hello_query);
}

0 comments on commit 4a7068d

Please sign in to comment.