Skip to content

Commit

Permalink
Merge pull request #46 from tirr-c/subrouter
Browse files Browse the repository at this point in the history
Subrouters and per-endpoint middleware
  • Loading branch information
tirr-c authored Nov 24, 2018
2 parents 17f4940 + 092cc1e commit 8cc895f
Show file tree
Hide file tree
Showing 5 changed files with 498 additions and 37 deletions.
37 changes: 37 additions & 0 deletions examples/simple_nested_router.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// A `Router`-nesting version of the example `named_path`.

#![feature(async_await, futures_api)]

use tide::{
head::{Named, NamedComponent},
Router,
};

struct Number(i32);

impl NamedComponent for Number {
const NAME: &'static str = "num";
}

impl std::str::FromStr for Number {
type Err = std::num::ParseIntError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse().map(|num| Number(num))
}
}

async fn add_two(Named(number): Named<Number>) -> String {
let Number(num) = number;
format!("{} plus two is {}", num, num + 2)
}

fn build_add_two<Data: Clone + Send + Sync + 'static>(router: &mut Router<Data>) {
router.at("{num}").get(add_two);
}

fn main() {
let mut app = tide::App::new(());
app.at("add_two").nest(build_add_two);
app.serve("127.0.0.1:8000");
}
26 changes: 16 additions & 10 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{
use crate::{
body::Body,
extract::Extract,
router::{Resource, Router},
router::{Resource, RouteResult, Router},
Middleware, Request, Response, RouteMatch,
};

Expand All @@ -24,7 +24,6 @@ use crate::{
pub struct App<Data> {
data: Data,
router: Router<Data>,
middleware: Vec<Box<dyn Middleware<Data> + Send + Sync>>,
}

impl<Data: Clone + Send + Sync + 'static> App<Data> {
Expand All @@ -33,26 +32,30 @@ impl<Data: Clone + Send + Sync + 'static> App<Data> {
App {
data,
router: Router::new(),
middleware: Vec::new(),
}
}

/// Get the top-level router.
pub fn router(&mut self) -> &mut Router<Data> {
&mut self.router
}

/// Add a new resource at `path`.
pub fn at<'a>(&'a mut self, path: &'a str) -> &mut Resource<Data> {
pub fn at<'a>(&'a mut self, path: &'a str) -> Resource<'a, Data> {
self.router.at(path)
}

/// Apply `middleware` to the whole app.
/// Apply `middleware` to the whole app. Note that the order of nesting subrouters and applying
/// middleware matters; see `Router` for details.
pub fn middleware(&mut self, middleware: impl Middleware<Data> + 'static) -> &mut Self {
self.middleware.push(Box::new(middleware));
self.router.middleware(middleware);
self
}

fn into_server(self) -> Server<Data> {
Server {
data: self.data,
router: Arc::new(self.router),
middleware: Arc::new(self.middleware),
}
}

Expand Down Expand Up @@ -84,7 +87,6 @@ impl<Data: Clone + Send + Sync + 'static> App<Data> {
struct Server<Data> {
data: Data,
router: Arc<Router<Data>>,
middleware: Arc<Vec<Box<dyn Middleware<Data> + Send + Sync>>>,
}

impl<Data: Clone + Send + Sync + 'static> Service for Server<Data> {
Expand All @@ -96,15 +98,19 @@ impl<Data: Clone + Send + Sync + 'static> Service for Server<Data> {
fn call(&mut self, req: http::Request<hyper::Body>) -> Self::Future {
let mut data = self.data.clone();
let router = self.router.clone();
let middleware = self.middleware.clone();

let mut req = req.map(Body::from);
let path = req.uri().path().to_owned();
let method = req.method().to_owned();

FutureObj::new(Box::new(
async move {
if let Some((endpoint, params)) = router.route(&path, &method) {
if let Some(RouteResult {
endpoint,
params,
middleware,
}) = router.route(&path, &method)
{
for m in middleware.iter() {
if let Err(resp) = await!(m.request(&mut data, &mut req, &params)) {
return Ok(resp.map(Into::into));
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ pub use crate::{
middleware::Middleware,
request::Request,
response::{IntoResponse, Response},
router::Resource,
router::{Resource, Router},
url_table::RouteMatch,
};
Loading

0 comments on commit 8cc895f

Please sign in to comment.