Skip to content

Commit

Permalink
Merge pull request #42 from tzilist/feat-default-headers
Browse files Browse the repository at this point in the history
Feature: Default Headers Middleware
  • Loading branch information
tirr-c authored Nov 15, 2018
2 parents 1dac61c + 145911b commit a724ef3
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 3 deletions.
16 changes: 16 additions & 0 deletions examples/default_headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![feature(async_await)]

use tide::middleware::DefaultHeaders;

fn main() {
let mut app = tide::App::new(());

app.middleware(
DefaultHeaders::new()
.header("X-Version", "1.0.0")
.header("X-Servier", "Tide"),
);

app.at("/").get(async || "Hello, world!");
app.serve("127.0.0.1:7878")
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub mod body;
mod endpoint;
mod extract;
pub mod head;
mod middleware;
pub mod middleware;
mod request;
mod response;
mod router;
Expand Down
49 changes: 49 additions & 0 deletions src/middleware/default_headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use futures::future::FutureObj;

use http::{
header::{HeaderValue, IntoHeaderName},
HeaderMap, HttpTryFrom,
};

use crate::{head::Head, Middleware, Response};

#[derive(Clone, Default)]
pub struct DefaultHeaders {
headers: HeaderMap,
}

impl DefaultHeaders {
pub fn new() -> DefaultHeaders {
DefaultHeaders::default()
}

#[inline]
pub fn header<K, V>(mut self, key: K, value: V) -> Self
where
K: IntoHeaderName,
HeaderValue: HttpTryFrom<V>,
{
let value = HeaderValue::try_from(value)
.map_err(Into::into)
.expect("Cannot create default header");

self.headers.append(key, value);

self
}
}

impl<Data> Middleware<Data> for DefaultHeaders {
fn response(
&self,
data: &mut Data,
head: &Head,
mut resp: Response,
) -> FutureObj<'static, Response> {
let headers = resp.headers_mut();
for (key, value) in self.headers.iter() {
headers.entry(key).unwrap().or_insert_with(|| value.clone());
}
FutureObj::new(Box::new(async { resp }))
}
}
12 changes: 10 additions & 2 deletions src/middleware.rs → src/middleware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ use futures::future::FutureObj;

use crate::{head::Head, Request, Response, RouteMatch};

mod default_headers;

pub use self::default_headers::DefaultHeaders;

/// Middleware for an app with state of type `Data`
pub trait Middleware<Data>: Send + Sync {
/// Asynchronously transform the incoming request, or abort further handling by immediately
Expand All @@ -11,15 +15,19 @@ pub trait Middleware<Data>: Send + Sync {
data: &mut Data,
req: Request,
params: &RouteMatch<'_>,
) -> FutureObj<'static, Result<Request, Response>>;
) -> FutureObj<'static, Result<Request, Response>> {
FutureObj::new(Box::new(async { Ok(req) }))
}

/// Asynchronously transform the outgoing response.
fn response(
&self,
data: &mut Data,
head: &Head,
resp: Response,
) -> FutureObj<'static, Response>;
) -> FutureObj<'static, Response> {
FutureObj::new(Box::new(async { resp }))
}

// TODO: provide the following, intended to fire *after* the body has been fully sent

Expand Down

0 comments on commit a724ef3

Please sign in to comment.