diff options
| -rw-r--r-- | askama/Cargo.toml | 3 | ||||
| -rw-r--r-- | askama/src/lib.rs | 28 | ||||
| -rw-r--r-- | askama_derive/Cargo.toml | 1 | ||||
| -rw-r--r-- | askama_derive/src/generator.rs | 23 | ||||
| -rw-r--r-- | askama_shared/Cargo.toml | 1 | 
5 files changed, 56 insertions, 0 deletions
diff --git a/askama/Cargo.toml b/askama/Cargo.toml index 638d43a..1e7f1ec 100644 --- a/askama/Cargo.toml +++ b/askama/Cargo.toml @@ -22,12 +22,15 @@ default = []  serde-json = ["askama_shared/serde-json"]  with-iron = ["iron", "askama_derive/iron"]  with-rocket = ["rocket", "askama_derive/rocket"] +with-actix-web = ["actix-web", "askama_derive/actix-web", "mime_guess"]  [dependencies]  askama_derive = { path = "../askama_derive", version = "0.7.0" }  askama_shared = { version = "0.7.0", path = "../askama_shared" }  iron = { version = ">= 0.5, < 0.7", optional = true }  rocket = { version = "0.3", optional = true } +actix-web = { version = "0.7", optional = true } +mime_guess = { version = "2.0.0-alpha", optional = true }  [package.metadata.docs.rs]  features = [ "serde-json" ] diff --git a/askama/src/lib.rs b/askama/src/lib.rs index c31f341..77e49f2 100644 --- a/askama/src/lib.rs +++ b/askama/src/lib.rs @@ -306,6 +306,12 @@  //! unwraps any run-time errors from the template. If you have a better  //! suggestion, please [file an issue](https://github.com/djc/askama/issues/new).  //! +//! ## Actix-web integration +//! +//! Enabling the `with-actix-web` feature appends an implementation of Actix-web's +//! `Responder` trait for each template type. This makes it easy to return a value of +//! that type in an Actix-web handler. +//!  //! ## The `json` filter  //!  //! Enabling the `serde-json` filter will enable the use of the `json` filter. @@ -366,6 +372,28 @@ pub mod rocket {      }  } +#[cfg(feature = "with-actix-web")] +pub mod actix_web { +    extern crate actix_web; +    extern crate mime_guess; + +    // actix_web technically has this as a pub fn in later versions, fs::file_extension_to_mime. +    // Older versions that don't have it exposed are easier this way. If ext is empty or no +    // associated type was found, then this returns `application/octet-stream`, in line with how +    // actix_web handles it in newer releases. +    pub use self::actix_web::{ +        error::ErrorInternalServerError, Error, HttpRequest, HttpResponse, Responder, +    }; +    use self::mime_guess::get_mime_type; + +    pub fn respond(t: &super::Template, ext: &str) -> Result<HttpResponse, Error> { +        let rsp = t.render() +            .map_err(|_| ErrorInternalServerError("Template parsing error"))?; +        let ctype = get_mime_type(ext).to_string(); +        Ok(HttpResponse::Ok().content_type(ctype.as_str()).body(rsp)) +    } +} +  fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {      if dir.is_dir() {          for entry in fs::read_dir(dir)? { diff --git a/askama_derive/Cargo.toml b/askama_derive/Cargo.toml index 1834852..774fb51 100644 --- a/askama_derive/Cargo.toml +++ b/askama_derive/Cargo.toml @@ -15,6 +15,7 @@ proc-macro = true  default = []  iron = ["askama_shared/iron"]  rocket = ["askama_shared/rocket"] +actix-web = ["askama_shared/actix-web"]  [dependencies]  askama_shared = { version = "0.7.0", path = "../askama_shared" } diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index f586e1c..5af38c0 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -94,6 +94,9 @@ impl<'a> Generator<'a> {          if cfg!(feature = "rocket") {              self.impl_rocket_responder();          } +        if cfg!(feature = "actix-web") { +            self.impl_actix_web_responder(); +        }          self.buf      } @@ -235,6 +238,26 @@ impl<'a> Generator<'a> {          self.writeln("}");      } +    // Implement Actix-web's `Responder`. +    fn impl_actix_web_responder(&mut self) { +        self.write_header("::askama::actix_web::Responder", None); +        self.writeln("type Item = ::askama::actix_web::HttpResponse;"); +        self.writeln("type Error = ::askama::actix_web::Error;"); +        self.writeln( +            "fn respond_to<S>(self, _req: &::askama::actix_web::HttpRequest<S>) \ +             -> Result<Self::Item, Self::Error> {", +        ); + +        let ext = match self.input.path.extension() { +            Some(s) => s.to_str().unwrap(), +            None => "txt", +        }; +        self.writeln(&format!("::askama::actix_web::respond(&self, {:?})", ext)); + +        self.writeln("}"); +        self.writeln("}"); +    } +      // Writes header for the `impl` for `TraitFromPathName` or `Template`      // for the given context struct.      fn write_header(&mut self, target: &str, params: Option<Vec<syn::GenericParam>>) { diff --git a/askama_shared/Cargo.toml b/askama_shared/Cargo.toml index cd052cf..5b93404 100644 --- a/askama_shared/Cargo.toml +++ b/askama_shared/Cargo.toml @@ -13,6 +13,7 @@ default = []  serde-json = ["serde_json"]  iron = []  rocket = [] +actix-web = []  [dependencies]  serde = "1.0"  | 
