Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core revamp part 2 #252

Merged
merged 8 commits into from
May 21, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ http-service = "0.2.0"
serde = "1.0.91"
serde_derive = "1.0.91"
serde_urlencoded = "0.5.5"
slog = "2.4.1"
slog-async = "2.3.0"
slog-term = "2.4.0"
tide-cookies = { path = "./tide-cookies", optional = true }
tide-core = { path = "./tide-core" }
tide-headers = { path = "./tide-headers" }
tide-log = { path = "./tide-log" }

[dependencies.multipart]
default-features = false
Expand All @@ -52,13 +51,19 @@ mime = "0.3.13"
mime_guess = "2.0.0-alpha.6"
percent-encoding = "1.0.1"
serde = { version = "1.0.91", features = ["derive"] }
tide-log = { path = "./tide-log" }
env_logger = "0.6.1"
log4rs = "0.8.3"
log = "0.4.6"

[workspace]
members = [
"tide-compression",
"tide-cookies",
"tide-core",
"tide-headers",
"tide-log",
"tide-slog",
]

[patch.crates-io]
Expand Down
8 changes: 8 additions & 0 deletions examples/hello_envlog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(async_await)]
fn main() {
env_logger::from_env(env_logger::Env::default().default_filter_or("info")).init();
let mut app = tide::App::new();
app.middleware(tide::middleware::RequestLogger::new());
app.at("/").get(async move |_| "Hello, world!");
app.run("127.0.0.1:8000").unwrap();
}
18 changes: 18 additions & 0 deletions examples/hello_logrs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![feature(async_await)]
fn main() {
use log::LevelFilter;
use log4rs::append::console::ConsoleAppender;
use log4rs::config::{Appender, Config, Root};

let stdout = ConsoleAppender::builder().build();
let config = Config::builder()
.appender(Appender::builder().build("stdout", Box::new(stdout)))
.build(Root::builder().appender("stdout").build(LevelFilter::Info))
.unwrap();
let _handle = log4rs::init_config(config).unwrap();

let mut app = tide::App::new();
app.middleware(tide::middleware::RequestLogger::new());
app.at("/").get(async move |_| "Hello, world!");
app.run("127.0.0.1:8000").unwrap();
}
10 changes: 6 additions & 4 deletions src/middleware/mod.rs → src/middleware.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod default_headers;
mod logger;
// Core
pub use tide_core::middleware::{Middleware, Next};

// Exports from tide repo.
pub use tide_headers::DefaultHeaders;
pub use tide_log::RequestLogger;

pub use self::{default_headers::DefaultHeaders, logger::RootLogger};
#[cfg(feature = "cookies")]
pub use tide_cookies::CookiesMiddleware;
pub use tide_core::middleware::{Middleware, Next};
23 changes: 23 additions & 0 deletions tide-headers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
authors = [
"Tide Developers"
]
description = "Header related middleware for tide"
fairingrey marked this conversation as resolved.
Show resolved Hide resolved
documentation = "https://docs.rs/tide-log"
keywords = ["tide", "web", "async", "middleware", "headers"]
categories = [
"network-programming",
"web-programming::http-server",
]
edition = "2018"
license = "MIT OR Apache-2.0"
name = "tide-headers"
readme = "README.md"
repository = "https://github.com/rustasync/tide"
version = "0.1.0"

[dependencies]
tide-core = { path = "../tide-core" }
futures-preview = "0.3.0-alpha.16"
http = "0.1"
log = "0.4.6"
19 changes: 14 additions & 5 deletions src/middleware/default_headers.rs → tide-headers/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
//! Crate that provides helpers, and/or middlewares for tide
//! related to http headers.
#![feature(async_await)]
#![warn(
nonstandard_style,
rust_2018_idioms,
future_incompatible,
missing_debug_implementations
)]

use futures::future::BoxFuture;
use futures::prelude::*;
use log::trace;

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

use crate::{
use tide_core::{
middleware::{Middleware, Next},
Context, Response,
};
Expand All @@ -20,10 +31,9 @@ pub struct DefaultHeaders {
impl DefaultHeaders {
/// Construct a new instance with an empty list of headers.
pub fn new() -> DefaultHeaders {
DefaultHeaders::default()
Self::default()
}

#[inline]
/// Add a header to the default header list.
pub fn header<K, V>(mut self, key: K, value: V) -> Self
where
Expand All @@ -35,7 +45,6 @@ impl DefaultHeaders {
.expect("Cannot create default header");

self.headers.append(key, value);

self
}
}
Expand All @@ -44,9 +53,9 @@ impl<Data: Send + Sync + 'static> Middleware<Data> for DefaultHeaders {
fn handle<'a>(&'a self, cx: Context<Data>, next: Next<'a, Data>) -> BoxFuture<'a, Response> {
FutureExt::boxed(async move {
let mut res = next.run(cx).await;

let headers = res.headers_mut();
for (key, value) in self.headers.iter() {
trace!("add default: {} {:?}", &key, &value);
headers.entry(key).unwrap().or_insert_with(|| value.clone());
}
res
Expand Down
6 changes: 3 additions & 3 deletions tide-log/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
authors = [
"Tide Developers"
]
description = "Tide middleware for logging"
description = "Logging middleware for tide"
fairingrey marked this conversation as resolved.
Show resolved Hide resolved
documentation = "https://docs.rs/tide-log"
keywords = ["tide", "web", "async", "middleware", "logging"]
categories = [
Expand All @@ -18,7 +18,7 @@ repository = "https://github.com/rustasync/tide"
version = "0.1.0"

[dependencies]
tide = { path = "../" }
tide-core = { path = "../tide-core" }
Nemo157 marked this conversation as resolved.
Show resolved Hide resolved
futures-preview = "0.3.0-alpha.16"
http = "0.1"
log = "0.4.6"
log = "0.4.6"
29 changes: 24 additions & 5 deletions tide-log/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Crate that provides helpers and/or middlewares for tide
//! related to logging.
//!
#![feature(async_await)]
#![warn(
nonstandard_style,
Expand All @@ -9,7 +12,8 @@
use futures::future::BoxFuture;
use futures::prelude::*;
use log::{info, trace};
use tide::{

use tide_core::{
middleware::{Middleware, Next},
Context, Response,
};
Expand All @@ -24,25 +28,40 @@ use tide::{
/// app.middleware(tide_log::RequestLogger::new());
/// ```
#[derive(Debug, Clone, Default)]
pub struct RequestLogger;
pub struct RequestLogger {
target: String,
}

impl RequestLogger {
/// Create a new instance of logger with default target as
/// "requests"
pub fn new() -> Self {
Self::default()
Self {
target: "requests".to_owned(),
}
}

/// Create a new instance of logger with supplied `target` for
/// logging.
pub fn with_target(target: String) -> Self {
Self {
target,
}
}

async fn log_basic<'a, Data: Send + Sync + 'static>(
&'a self,
ctx: Context<Data>,
next: Next<'a, Data>,
) -> tide::Response {
) -> Response {
let path = ctx.uri().path().to_owned();
let method = ctx.method().as_str().to_owned();
trace!("IN => {} {}", method, path);
trace!(target: &self.target, "IN => {} {}", method, path);
let start = std::time::Instant::now();
let res = next.run(ctx).await;
let status = res.status();
info!(
target: &self.target,
"{} {} {} {}ms",
method,
path,
Expand Down
27 changes: 27 additions & 0 deletions tide-slog/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
authors = [
"Tide Developers"
]
description = "Logging middleware for tide based on slog"
fairingrey marked this conversation as resolved.
Show resolved Hide resolved
documentation = "https://docs.rs/tide-log"
keywords = ["tide", "web", "async", "middleware", "logging", "slog"]
categories = [
"logging",
"network-programming",
"web-programming::http-server",
]
edition = "2018"
license = "MIT OR Apache-2.0"
name = "tide-slog"
readme = "README.md"
repository = "https://github.com/rustasync/tide"
version = "0.1.0"

[dependencies]
tide-core = { path = "../tide-core" }
futures-preview = "0.3.0-alpha.16"
http = "0.1"
log = "0.4.6"
slog = "2.4.1"
slog-async = "2.3.0"
slog-term = "2.4.0"
54 changes: 37 additions & 17 deletions src/middleware/logger.rs → tide-slog/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,70 @@
use slog::{info, o, Drain};
#![feature(async_await)]
#![warn(
nonstandard_style,
rust_2018_idioms,
future_incompatible,
missing_debug_implementations
)]

use slog::{info, trace, o, Drain};
use slog_async;
use slog_term;

use futures::future::BoxFuture;
use futures::prelude::*;

use crate::{
use tide_core::{
middleware::{Middleware, Next},
Context, Response,
};

/// Root logger for Tide. Wraps over logger provided by slog.SimpleLogger
/// RequestLogger based on slog.SimpleLogger
#[derive(Debug)]
pub struct RootLogger {
pub struct RequestLogger {
// drain: dyn slog::Drain,
inner_logger: slog::Logger,
inner: slog::Logger,
}

impl RootLogger {
pub fn new() -> RootLogger {
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
let drain = slog_async::Async::new(drain).build().fuse();
impl RequestLogger {
pub fn new() -> Self {
Default::default()
}

let log = slog::Logger::root(drain, o!());
RootLogger { inner_logger: log }
pub fn with_logger(logger: slog::Logger) -> Self {
Self { inner: logger }
}
}

impl Default for RootLogger {
impl Default for RequestLogger {
Nemo157 marked this conversation as resolved.
Show resolved Hide resolved
fn default() -> Self {
Self::new()
let decorator = slog_term::TermDecorator::new().build();
let drain = slog_term::CompactFormat::new(decorator).build().fuse();
let drain = slog_async::Async::new(drain).build().fuse();

let log = slog::Logger::root(drain, o!());
Self { inner: log }
}
}

/// Stores information during request phase and logs information once the response
/// is generated.
impl<Data: Send + Sync + 'static> Middleware<Data> for RootLogger {
impl<Data: Send + Sync + 'static> Middleware<Data> for RequestLogger {
fn handle<'a>(&'a self, cx: Context<Data>, next: Next<'a, Data>) -> BoxFuture<'a, Response> {
FutureExt::boxed(async move {
let path = cx.uri().path().to_owned();
let method = cx.method().as_str().to_owned();

trace!(self.inner, "IN => {} {}", method, path);
let start = std::time::Instant::now();
let res = next.run(cx).await;
let status = res.status();
info!(self.inner_logger, "{} {} {}", method, path, status.as_str());
info!(
self.inner,
"{} {} {} {}ms",
method,
path,
status.as_str(),
start.elapsed().as_millis()
);
res
})
}
Expand Down