mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 15:25:19 +00:00
Move Actix-Web integration into separate askama_actix crate
This commit is contained in:
parent
9026f616e6
commit
b56c11639f
29
.github/workflows/rust.yml
vendored
29
.github/workflows/rust.yml
vendored
@ -29,11 +29,10 @@ jobs:
|
|||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --workspace --all-targets
|
args: --all-targets
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --workspace
|
|
||||||
|
|
||||||
stable-integrations:
|
stable-integrations:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -48,6 +47,20 @@ jobs:
|
|||||||
cd testing
|
cd testing
|
||||||
cargo test --features full
|
cargo test --features full
|
||||||
|
|
||||||
|
Actix-Web:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
components: clippy
|
||||||
|
- run: |
|
||||||
|
cargo test --package askama_actix --all-targets
|
||||||
|
cargo clippy --package askama_actix --all-targets -- -D warnings
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@ -71,12 +84,6 @@ jobs:
|
|||||||
toolchain: stable
|
toolchain: stable
|
||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- uses: actions-rs/cargo@v1
|
- run: |
|
||||||
with:
|
cargo fmt --all -- --check
|
||||||
command: fmt
|
cargo clippy --all-targets -- -D warnings
|
||||||
args: --all -- --check
|
|
||||||
- uses: actions-rs/cargo@v1
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
command: clippy
|
|
||||||
args: --workspace --all-targets -- -D warnings
|
|
||||||
|
16
Cargo.toml
16
Cargo.toml
@ -1,2 +1,16 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["askama", "askama_derive", "askama_escape", "askama_shared", "testing"]
|
members = [
|
||||||
|
"askama",
|
||||||
|
"askama_actix",
|
||||||
|
"askama_derive",
|
||||||
|
"askama_escape",
|
||||||
|
"askama_shared",
|
||||||
|
"testing",
|
||||||
|
]
|
||||||
|
default-members = [
|
||||||
|
"askama",
|
||||||
|
"askama_derive",
|
||||||
|
"askama_escape",
|
||||||
|
"askama_shared",
|
||||||
|
"testing",
|
||||||
|
]
|
||||||
|
@ -26,7 +26,7 @@ serde-yaml = ["askama_shared/yaml"]
|
|||||||
num-traits = ["askama_shared/num-traits"]
|
num-traits = ["askama_shared/num-traits"]
|
||||||
with-iron = ["iron", "askama_derive/iron"]
|
with-iron = ["iron", "askama_derive/iron"]
|
||||||
with-rocket = ["rocket", "askama_derive/rocket"]
|
with-rocket = ["rocket", "askama_derive/rocket"]
|
||||||
with-actix-web = ["actix-web", "askama_derive/actix-web", "mime", "mime_guess", "bytes", "futures"]
|
with-actix-web = ["askama_derive/actix-web"]
|
||||||
with-gotham = ["gotham", "askama_derive/gotham", "hyper", "mime", "mime_guess"]
|
with-gotham = ["gotham", "askama_derive/gotham", "hyper", "mime", "mime_guess"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -35,13 +35,10 @@ askama_escape = { version = "0.3.0", path = "../askama_escape" }
|
|||||||
askama_shared = { version = "0.9.0", path = "../askama_shared", default-features = false }
|
askama_shared = { version = "0.9.0", path = "../askama_shared", default-features = false }
|
||||||
iron = { version = ">= 0.5, < 0.7", optional = true }
|
iron = { version = ">= 0.5, < 0.7", optional = true }
|
||||||
rocket = { version = "0.4", default-features = false, optional = true }
|
rocket = { version = "0.4", default-features = false, optional = true }
|
||||||
actix-web = { version = "2", optional = true }
|
|
||||||
futures = { version = "0.3", optional = true }
|
|
||||||
mime = { version = "0.3", optional = true }
|
mime = { version = "0.3", optional = true }
|
||||||
mime_guess = { version = "2.0.0-alpha", optional = true }
|
mime_guess = { version = "2.0.0-alpha", optional = true }
|
||||||
gotham = { version = "0.3", default-features = false, optional = true }
|
gotham = { version = "0.3", default-features = false, optional = true }
|
||||||
hyper = { version = "0.12", optional = true }
|
hyper = { version = "0.12", optional = true }
|
||||||
bytes = { version = "0.5", optional = true }
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["config", "humansize", "num-traits", "serde-json", "serde-yaml"]
|
features = ["config", "humansize", "num-traits", "serde-json", "serde-yaml"]
|
||||||
|
@ -542,65 +542,33 @@ pub mod rocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "mime_guess", feature = "mime"))]
|
pub mod mime {
|
||||||
fn get_mime_type(ext: &str) -> mime_guess::Mime {
|
#[cfg(all(feature = "mime_guess", feature = "mime"))]
|
||||||
let basic_type = mime_guess::from_ext(ext).first_or_octet_stream();
|
pub fn extension_to_mime_type(ext: &str) -> mime_guess::Mime {
|
||||||
for (simple, utf_8) in &TEXT_TYPES {
|
let basic_type = mime_guess::from_ext(ext).first_or_octet_stream();
|
||||||
if &basic_type == simple {
|
for (simple, utf_8) in &TEXT_TYPES {
|
||||||
return utf_8.clone();
|
if &basic_type == simple {
|
||||||
|
return utf_8.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
basic_type
|
||||||
basic_type
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(feature = "mime_guess", feature = "mime"))]
|
|
||||||
const TEXT_TYPES: [(mime_guess::Mime, mime_guess::Mime); 6] = [
|
|
||||||
(mime::TEXT_PLAIN, mime::TEXT_PLAIN_UTF_8),
|
|
||||||
(mime::TEXT_HTML, mime::TEXT_HTML_UTF_8),
|
|
||||||
(mime::TEXT_CSS, mime::TEXT_CSS_UTF_8),
|
|
||||||
(mime::TEXT_CSV, mime::TEXT_CSV_UTF_8),
|
|
||||||
(
|
|
||||||
mime::TEXT_TAB_SEPARATED_VALUES,
|
|
||||||
mime::TEXT_TAB_SEPARATED_VALUES_UTF_8,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
mime::APPLICATION_JAVASCRIPT,
|
|
||||||
mime::APPLICATION_JAVASCRIPT_UTF_8,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
#[cfg(feature = "with-actix-web")]
|
|
||||||
pub mod actix_web {
|
|
||||||
use actix_web;
|
|
||||||
use bytes;
|
|
||||||
use mime_guess;
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait TemplateIntoResponse {
|
|
||||||
fn into_response(&self) -> Result<HttpResponse, Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: super::Template> TemplateIntoResponse for T {
|
#[cfg(all(feature = "mime_guess", feature = "mime"))]
|
||||||
fn into_response(&self) -> Result<HttpResponse, Error> {
|
const TEXT_TYPES: [(mime_guess::Mime, mime_guess::Mime); 6] = [
|
||||||
let mut buffer = actix_web::web::BytesMut::with_capacity(self.size_hint());
|
(mime::TEXT_PLAIN, mime::TEXT_PLAIN_UTF_8),
|
||||||
self.render_into(&mut buffer)
|
(mime::TEXT_HTML, mime::TEXT_HTML_UTF_8),
|
||||||
.map_err(|_| ErrorInternalServerError("Template parsing error"))?;
|
(mime::TEXT_CSS, mime::TEXT_CSS_UTF_8),
|
||||||
|
(mime::TEXT_CSV, mime::TEXT_CSV_UTF_8),
|
||||||
let ctype = super::get_mime_type(self.extension().unwrap_or("txt")).to_string();
|
(
|
||||||
Ok(HttpResponse::Ok()
|
mime::TEXT_TAB_SEPARATED_VALUES,
|
||||||
.content_type(ctype.as_str())
|
mime::TEXT_TAB_SEPARATED_VALUES_UTF_8,
|
||||||
.body(buffer.freeze()))
|
),
|
||||||
}
|
(
|
||||||
}
|
mime::APPLICATION_JAVASCRIPT,
|
||||||
|
mime::APPLICATION_JAVASCRIPT_UTF_8,
|
||||||
|
),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with-gotham")]
|
#[cfg(feature = "with-gotham")]
|
||||||
@ -611,7 +579,7 @@ pub mod gotham {
|
|||||||
pub use hyper::{Body, Response, StatusCode};
|
pub use hyper::{Body, Response, StatusCode};
|
||||||
|
|
||||||
pub fn respond<T: super::Template>(t: &T, ext: &str) -> Response<Body> {
|
pub fn respond<T: super::Template>(t: &T, ext: &str) -> Response<Body> {
|
||||||
let mime_type = super::get_mime_type(ext).to_string();
|
let mime_type = super::mime::extension_to_mime_type(ext).to_string();
|
||||||
|
|
||||||
match t.render() {
|
match t.render() {
|
||||||
Ok(body) => Response::builder()
|
Ok(body) => Response::builder()
|
||||||
|
22
askama_actix/Cargo.toml
Normal file
22
askama_actix/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "askama_actix"
|
||||||
|
version = "0.9.0"
|
||||||
|
authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>"]
|
||||||
|
description = "Actix-Web integration for Askama templates"
|
||||||
|
documentation = "https://docs.rs/askama"
|
||||||
|
keywords = ["markup", "template", "jinja2", "html"]
|
||||||
|
categories = ["template-engine"]
|
||||||
|
homepage = "https://github.com/djc/askama"
|
||||||
|
repository = "https://github.com/djc/askama"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
workspace = ".."
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = { version = "2" }
|
||||||
|
askama = { version = "0.9.0", path = "../askama", features = ["with-actix-web", "mime", "mime_guess"] }
|
||||||
|
bytes = { version = "0.5" }
|
||||||
|
futures = { version = "0.3" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
actix-rt = { version = "1", default-features = false }
|
22
askama_actix/src/lib.rs
Normal file
22
askama_actix/src/lib.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
pub use askama::*;
|
||||||
|
use bytes::BytesMut;
|
||||||
|
|
||||||
|
use actix_web::{error::ErrorInternalServerError, Error, HttpResponse};
|
||||||
|
|
||||||
|
pub trait TemplateIntoResponse {
|
||||||
|
fn into_response(&self) -> ::std::result::Result<HttpResponse, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: askama::Template> TemplateIntoResponse for T {
|
||||||
|
fn into_response(&self) -> ::std::result::Result<HttpResponse, Error> {
|
||||||
|
let mut buffer = BytesMut::with_capacity(self.size_hint());
|
||||||
|
self.render_into(&mut buffer)
|
||||||
|
.map_err(|_| ErrorInternalServerError("Template parsing error"))?;
|
||||||
|
|
||||||
|
let ctype =
|
||||||
|
askama::mime::extension_to_mime_type(self.extension().unwrap_or("txt")).to_string();
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ctype.as_str())
|
||||||
|
.body(buffer.freeze()))
|
||||||
|
}
|
||||||
|
}
|
1
askama_actix/templates/hello.html
Normal file
1
askama_actix/templates/hello.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello, {{ name }}!
|
@ -1,8 +1,7 @@
|
|||||||
#![cfg(feature = "actix")]
|
|
||||||
use actix_web::http::header::CONTENT_TYPE;
|
use actix_web::http::header::CONTENT_TYPE;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use askama::{actix_web::TemplateIntoResponse, Template};
|
use askama_actix::{Template, TemplateIntoResponse};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
@ -241,15 +241,15 @@ impl<'a> Generator<'a> {
|
|||||||
|
|
||||||
// Implement Actix-web's `Responder`.
|
// Implement Actix-web's `Responder`.
|
||||||
fn impl_actix_web_responder(&mut self, buf: &mut Buffer) {
|
fn impl_actix_web_responder(&mut self, buf: &mut Buffer) {
|
||||||
self.write_header(buf, "::askama::actix_web::Responder", None);
|
self.write_header(buf, "::actix_web::Responder", None);
|
||||||
buf.writeln("type Future = ::futures::future::Ready<::std::result::Result<::askama::actix_web::HttpResponse, Self::Error>>;");
|
buf.writeln("type Future = ::futures::future::Ready<::std::result::Result<::actix_web::HttpResponse, Self::Error>>;");
|
||||||
buf.writeln("type Error = ::askama::actix_web::Error;");
|
buf.writeln("type Error = ::actix_web::Error;");
|
||||||
buf.writeln(
|
buf.writeln(
|
||||||
"fn respond_to(self, _req: &::askama::actix_web::HttpRequest) \
|
"fn respond_to(self, _req: &::actix_web::HttpRequest) \
|
||||||
-> Self::Future {",
|
-> Self::Future {",
|
||||||
);
|
);
|
||||||
|
|
||||||
buf.writeln("use ::askama::actix_web::TemplateIntoResponse;");
|
buf.writeln("use ::askama_actix::TemplateIntoResponse;");
|
||||||
buf.writeln("::futures::future::ready(self.into_response())");
|
buf.writeln("::futures::future::ready(self.into_response())");
|
||||||
|
|
||||||
buf.writeln("}");
|
buf.writeln("}");
|
||||||
|
@ -6,20 +6,15 @@ workspace = ".."
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
actix = ["actix-web", "actix-rt", "bytes", "askama/with-actix-web", "futures"]
|
|
||||||
default = []
|
default = []
|
||||||
full = ["actix", "with-iron", "serde-json", "with-gotham"]
|
full = ["with-iron", "serde-json", "with-gotham"]
|
||||||
serde-json = ["serde_json", "askama/serde-json"]
|
serde-json = ["serde_json", "askama/serde-json"]
|
||||||
with-rocket = ["rocket", "askama/with-rocket"]
|
with-rocket = ["rocket", "askama/with-rocket"]
|
||||||
with-iron = ["iron", "askama/with-iron"]
|
with-iron = ["iron", "askama/with-iron"]
|
||||||
with-gotham = ["gotham", "askama/with-gotham", "mime", "hyper"]
|
with-gotham = ["gotham", "askama/with-gotham", "mime", "hyper"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "2", optional = true }
|
|
||||||
actix-rt = { version = "1", optional = true }
|
|
||||||
futures = { version = "0.3", optional = true }
|
|
||||||
askama = { path = "../askama", version = "*" }
|
askama = { path = "../askama", version = "*" }
|
||||||
bytes = { version = "0.5", optional = true }
|
|
||||||
iron = { version = "0.6", optional = true }
|
iron = { version = "0.6", optional = true }
|
||||||
rocket = { version = "0.4", default-features = false, optional = true }
|
rocket = { version = "0.4", default-features = false, optional = true }
|
||||||
serde_json = { version = "1.0", optional = true }
|
serde_json = { version = "1.0", optional = true }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user