mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 07:20:55 +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
|
||||
with:
|
||||
command: build
|
||||
args: --workspace --all-targets
|
||||
args: --all-targets
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --workspace
|
||||
|
||||
stable-integrations:
|
||||
runs-on: ubuntu-latest
|
||||
@ -48,6 +47,20 @@ jobs:
|
||||
cd testing
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -71,12 +84,6 @@ jobs:
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
- uses: actions-rs/cargo@v1
|
||||
if: always()
|
||||
with:
|
||||
command: clippy
|
||||
args: --workspace --all-targets -- -D warnings
|
||||
- run: |
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
|
16
Cargo.toml
16
Cargo.toml
@ -1,2 +1,16 @@
|
||||
[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"]
|
||||
with-iron = ["iron", "askama_derive/iron"]
|
||||
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"]
|
||||
|
||||
[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 }
|
||||
iron = { version = ">= 0.5, < 0.7", 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_guess = { version = "2.0.0-alpha", optional = true }
|
||||
gotham = { version = "0.3", default-features = false, optional = true }
|
||||
hyper = { version = "0.12", optional = true }
|
||||
bytes = { version = "0.5", optional = true }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["config", "humansize", "num-traits", "serde-json", "serde-yaml"]
|
||||
|
@ -542,65 +542,33 @@ pub mod rocket {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "mime_guess", feature = "mime"))]
|
||||
fn get_mime_type(ext: &str) -> mime_guess::Mime {
|
||||
let basic_type = mime_guess::from_ext(ext).first_or_octet_stream();
|
||||
for (simple, utf_8) in &TEXT_TYPES {
|
||||
if &basic_type == simple {
|
||||
return utf_8.clone();
|
||||
pub mod mime {
|
||||
#[cfg(all(feature = "mime_guess", feature = "mime"))]
|
||||
pub fn extension_to_mime_type(ext: &str) -> mime_guess::Mime {
|
||||
let basic_type = mime_guess::from_ext(ext).first_or_octet_stream();
|
||||
for (simple, utf_8) in &TEXT_TYPES {
|
||||
if &basic_type == simple {
|
||||
return utf_8.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
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>;
|
||||
basic_type
|
||||
}
|
||||
|
||||
impl<T: super::Template> TemplateIntoResponse for T {
|
||||
fn into_response(&self) -> Result<HttpResponse, Error> {
|
||||
let mut buffer = actix_web::web::BytesMut::with_capacity(self.size_hint());
|
||||
self.render_into(&mut buffer)
|
||||
.map_err(|_| ErrorInternalServerError("Template parsing error"))?;
|
||||
|
||||
let ctype = super::get_mime_type(self.extension().unwrap_or("txt")).to_string();
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type(ctype.as_str())
|
||||
.body(buffer.freeze()))
|
||||
}
|
||||
}
|
||||
#[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-gotham")]
|
||||
@ -611,7 +579,7 @@ pub mod gotham {
|
||||
pub use hyper::{Body, Response, StatusCode};
|
||||
|
||||
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() {
|
||||
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::test;
|
||||
use actix_web::web;
|
||||
use askama::{actix_web::TemplateIntoResponse, Template};
|
||||
use askama_actix::{Template, TemplateIntoResponse};
|
||||
use bytes::Bytes;
|
||||
|
||||
#[derive(Template)]
|
@ -241,15 +241,15 @@ impl<'a> Generator<'a> {
|
||||
|
||||
// Implement Actix-web's `Responder`.
|
||||
fn impl_actix_web_responder(&mut self, buf: &mut Buffer) {
|
||||
self.write_header(buf, "::askama::actix_web::Responder", None);
|
||||
buf.writeln("type Future = ::futures::future::Ready<::std::result::Result<::askama::actix_web::HttpResponse, Self::Error>>;");
|
||||
buf.writeln("type Error = ::askama::actix_web::Error;");
|
||||
self.write_header(buf, "::actix_web::Responder", None);
|
||||
buf.writeln("type Future = ::futures::future::Ready<::std::result::Result<::actix_web::HttpResponse, Self::Error>>;");
|
||||
buf.writeln("type Error = ::actix_web::Error;");
|
||||
buf.writeln(
|
||||
"fn respond_to(self, _req: &::askama::actix_web::HttpRequest) \
|
||||
"fn respond_to(self, _req: &::actix_web::HttpRequest) \
|
||||
-> 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("}");
|
||||
|
@ -6,20 +6,15 @@ workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
actix = ["actix-web", "actix-rt", "bytes", "askama/with-actix-web", "futures"]
|
||||
default = []
|
||||
full = ["actix", "with-iron", "serde-json", "with-gotham"]
|
||||
full = ["with-iron", "serde-json", "with-gotham"]
|
||||
serde-json = ["serde_json", "askama/serde-json"]
|
||||
with-rocket = ["rocket", "askama/with-rocket"]
|
||||
with-iron = ["iron", "askama/with-iron"]
|
||||
with-gotham = ["gotham", "askama/with-gotham", "mime", "hyper"]
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "2", optional = true }
|
||||
actix-rt = { version = "1", optional = true }
|
||||
futures = { version = "0.3", optional = true }
|
||||
askama = { path = "../askama", version = "*" }
|
||||
bytes = { version = "0.5", optional = true }
|
||||
iron = { version = "0.6", optional = true }
|
||||
rocket = { version = "0.4", default-features = false, optional = true }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
|
Loading…
x
Reference in New Issue
Block a user