Skip to content

Rewind page 3 #340

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

Merged
merged 7 commits into from
Oct 31, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
run: cargo fmt --all -- --check

- name: Docs
run: cargo doc --features docs
run: cargo doc

clippy_check:
name: Clippy check
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://book.async.rs/overview

## [Unreleased]

### Added

- Added `logger::RequestLogger` based on `log` (replaces `logger:RootLogger`)

### Changed

- Resolved an `#[allow(unused_mut)]` workaround.
- Renamed `ExtractForms` to `ContextExt`.

### Removed

- Removed `logger::RootLogger` (replaced by `logger:RequestLogger`)
- Removed internal use of the `box_async` macro

## [0.3.0] - 2019-10-31

This is the first release in almost 6 months; introducing a snapshot of where we
Expand Down
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ route-recognizer = "0.1.13"
serde = "1.0.102"
serde_derive = "1.0.102"
serde_json = "1.0.41"
slog = "2.5.2"
slog-async = "2.3.0"
slog-term = "2.4.2"
typemap = "0.3.3"
serde_urlencoded = "0.6.1"
log = "0.4.8"

[dependencies.http-service-hyper]
optional = true
Expand Down
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
API Docs
</a>
<span> | </span>
<a href="https://github.com/rustasync/tide/blob/master/.github/CONTRIBUTING.md">
<a href="https://github.com/http-rs/tide/blob/master/.github/CONTRIBUTING.md">
Contributing
</a>
<span> | </span>
Expand Down Expand Up @@ -60,23 +60,23 @@ fn main() -> Result<(), std::io::Error> {

**More Examples**

- [Hello World](https://github.com/rustasync/tide/tree/master/examples/hello.rs)
- [Messages](https://github.com/rustasync/tide/blob/master/examples/messages.rs)
- [Body Types](https://github.com/rustasync/tide/blob/master/examples/body_types.rs)
- [Multipart Form](https://github.com/rustasync/tide/tree/master/examples/multipart-form/main.rs)
- [Catch All](https://github.com/rustasync/tide/tree/master/examples/catch_all.rs)
- [Cookies](https://github.com/rustasync/tide/tree/master/examples/cookies.rs)
- [Default Headers](https://github.com/rustasync/tide/tree/master/examples/default_headers.rs)
- [GraphQL](https://github.com/rustasync/tide/tree/master/examples/graphql.rs)
- [Hello World](https://github.com/http-rs/tide/tree/master/examples/hello.rs)
- [Messages](https://github.com/http-rs/tide/blob/master/examples/messages.rs)
- [Body Types](https://github.com/http-rs/tide/blob/master/examples/body_types.rs)
- [Multipart Form](https://github.com/http-rs/tide/tree/master/examples/multipart-form/main.rs)
- [Catch All](https://github.com/http-rs/tide/tree/master/examples/catch_all.rs)
- [Cookies](https://github.com/http-rs/tide/tree/master/examples/cookies.rs)
- [Default Headers](https://github.com/http-rs/tide/tree/master/examples/default_headers.rs)
- [GraphQL](https://github.com/http-rs/tide/tree/master/examples/graphql.rs)

## Resources

Read about the design here:

- [Rising Tide: building a modular web framework in the open](https://rustasync.github.io/team/2018/09/11/tide.html)
- [Routing and extraction in Tide: a first sketch](https://rustasync.github.io/team/2018/10/16/tide-routing.html)
- [Middleware in Tide](https://rustasync.github.io/team/2018/11/07/tide-middleware.html)
- [Tide's evolving middleware approach](https://rustasync.github.io/team/2018/11/27/tide-middleware-evolution.html)
- [Rising Tide: building a modular web framework in the open](https://http-rs.github.io/team/2018/09/11/tide.html)
- [Routing and extraction in Tide: a first sketch](https://http-rs.github.io/team/2018/10/16/tide-routing.html)
- [Middleware in Tide](https://http-rs.github.io/team/2018/11/07/tide-middleware.html)
- [Tide's evolving middleware approach](https://http-rs.github.io/team/2018/11/27/tide-middleware-evolution.html)

## Contributing

Expand All @@ -89,7 +89,7 @@ guide][contributing] and take a look at some of these issues:
#### Conduct

The Tide project adheres to the [Contributor Covenant Code of
Conduct](https://github.com/rustasync/tide/blob/master/.github/CODE_OF_CONDUCT.md). This
Conduct](https://github.com/http-rs/tide/blob/master/.github/CODE_OF_CONDUCT.md). This
describes the minimum behavior expected from all contributors.

## License
Expand All @@ -107,7 +107,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

[releases]: https://github.com/rustasync/tide/releases
[contributing]: https://github.com/rustasync/tide/blob/master/.github/CONTRIBUTING.md
[good-first-issue]: https://github.com/rustasync/tide/labels/good%20first%20issue
[help-wanted]: https://github.com/rustasync/tide/labels/help%20wanted
[releases]: https://github.com/http-rs/tide/releases
[contributing]: https://github.com/http-rs/tide/blob/master/.github/CONTRIBUTING.md
[good-first-issue]: https://github.com/http-rs/tide/labels/good%20first%20issue
[help-wanted]: https://github.com/http-rs/tide/labels/help%20wanted
6 changes: 1 addition & 5 deletions examples/body_types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tide::{
error::ResultExt,
forms::{self, ExtractForms},
forms::{self, ContextExt},
response, App, Context, EndpointResult,
};

Expand All @@ -11,28 +11,24 @@ struct Message {
contents: String,
}

#[allow(unused_mut)] // Workaround clippy bug
async fn echo_string(mut cx: Context<()>) -> String {
let msg = cx.body_string().await.unwrap();
println!("String: {}", msg);
msg
}

#[allow(unused_mut)] // Workaround clippy bug
async fn echo_bytes(mut cx: Context<()>) -> Vec<u8> {
let msg = cx.body_bytes().await.unwrap();
println!("Bytes: {:?}", msg);
msg
}

#[allow(unused_mut)] // Workaround clippy bug
async fn echo_json(mut cx: Context<()>) -> EndpointResult {
let msg = cx.body_json().await.client_err()?;
println!("JSON: {:?}", msg);
Ok(response::json(msg))
}

#[allow(unused_mut)] // Workaround clippy bug
async fn echo_form(mut cx: Context<()>) -> EndpointResult {
let msg = cx.body_form().await?;
println!("Form: {:?}", msg);
Expand Down
2 changes: 0 additions & 2 deletions examples/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ async fn retrieve_cookie(mut cx: Context<()>) -> String {
format!("hello cookies: {:?}", cx.get_cookie("hello").unwrap())
}

#[allow(unused_mut)] // Workaround clippy bug
async fn set_cookie(mut cx: Context<()>) {
cx.set_cookie(Cookie::new("hello", "world")).unwrap();
}

#[allow(unused_mut)] // Workaround clippy bug
async fn remove_cookie(mut cx: Context<()>) {
cx.remove_cookie(Cookie::named("hello")).unwrap();
}
Expand Down
2 changes: 0 additions & 2 deletions examples/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@ impl Database {
}
}

#[allow(unused_mut)] // Workaround clippy bug
async fn new_message(mut cx: Context<Database>) -> EndpointResult<String> {
let msg = cx.body_json().await.client_err()?;
Ok(cx.state().insert(msg).to_string())
}

#[allow(unused_mut)] // Workaround clippy bug
async fn set_message(mut cx: Context<Database>) -> EndpointResult<()> {
let msg = cx.body_json().await.client_err()?;
let id = cx.param("id").client_err()?;
Expand Down
3 changes: 1 addition & 2 deletions examples/multipart-form/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use std::io::Read;
use tide::{forms::ExtractForms, response, App, Context, EndpointResult};
use tide::{forms::ContextExt, response, App, Context, EndpointResult};

#[derive(Serialize, Deserialize, Clone)]
struct Message {
Expand All @@ -9,7 +9,6 @@ struct Message {
file: Option<String>,
}

#[allow(unused_mut)] // Workaround clippy bug
async fn upload_file(mut cx: Context<()>) -> EndpointResult {
// https://stackoverflow.com/questions/43424982/how-to-parse-multipart-forms-using-abonander-multipart-with-rocket
let mut message = Message {
Expand Down
9 changes: 4 additions & 5 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
///
/// let mut app = tide::App::new();
/// app.at("/hello").get(|_| async move {"Hello, world!"});
/// app.serve("127.0.0.1:8000");
/// app.serve("127.0.0.1:8000").unwrap();
/// ```
///
/// # Routing and parameters
Expand All @@ -44,7 +44,6 @@ use crate::{
/// segments as parameters to endpoints:
///
/// ```rust, no_run
///
/// use tide::error::ResultExt;
///
/// async fn hello(cx: tide::Context<()>) -> tide::EndpointResult<String> {
Expand All @@ -65,7 +64,7 @@ use crate::{
/// "Use /hello/{your name} or /goodbye/{your name}"
/// });
///
/// app.serve("127.0.0.1:8000");
/// app.serve("127.0.0.1:8000").unwrap();
/// ```
///
/// You can learn more about routing in the [`App::at`] documentation.
Expand Down Expand Up @@ -272,7 +271,7 @@ impl<State: Sync + Send + 'static> HttpService for Server<State> {
let middleware = self.middleware.clone();
let data = self.data.clone();

box_async! {
Box::pin(async move {
let fut = {
let Selection { endpoint, params } = router.route(&path, method);
let cx = Context::new(data, req, params);
Expand All @@ -286,7 +285,7 @@ impl<State: Sync + Send + 'static> HttpService for Server<State> {
};

Ok(fut.await)
}
})
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ where
type Fut = BoxFuture<'static, Response>;
fn call(&self, cx: Context<State>) -> Self::Fut {
let fut = (self)(cx);
box_async! {
fut.await.into_response()
}
Box::pin(async move { fut.await.into_response() })
}
}
20 changes: 12 additions & 8 deletions src/forms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ use crate::{
};

/// An extension trait for `Context`, providing form extraction.
pub trait ExtractForms {
pub trait ContextExt {
/// Asynchronously extract the entire body as a single form.
fn body_form<T: serde::de::DeserializeOwned>(&mut self) -> BoxTryFuture<T>;

/// Asynchronously extract the entire body as a multipart form.
fn body_multipart(&mut self) -> BoxTryFuture<Multipart<Cursor<Vec<u8>>>>;
}

impl<State: Send + Sync + 'static> ExtractForms for Context<State> {
impl<State: Send + Sync + 'static> ContextExt for Context<State> {
fn body_form<T: serde::de::DeserializeOwned>(&mut self) -> BoxTryFuture<T> {
let body = self.take_body();
box_async! {
Box::pin(async move {
let body = body.into_vec().await.client_err()?;
Ok(serde_urlencoded::from_bytes(&body).map_err(|e| err_fmt!("could not decode form: {}", e)).client_err()?)
}
Ok(serde_urlencoded::from_bytes(&body)
.map_err(|e| err_fmt!("could not decode form: {}", e))
.client_err()?)
})
}

fn body_multipart(&mut self) -> BoxTryFuture<Multipart<Cursor<Vec<u8>>>> {
Expand All @@ -35,11 +37,13 @@ impl<State: Send + Sync + 'static> ExtractForms for Context<State> {

let body = self.take_body();

box_async! {
Box::pin(async move {
let body = body.into_vec().await.client_err()?;
let boundary = boundary.ok_or_else(|| err_fmt!("no boundary found")).client_err()?;
let boundary = boundary
.ok_or_else(|| err_fmt!("no boundary found"))
.client_err()?;
Ok(Multipart::with_body(Cursor::new(body), boundary))
}
})
}
}

Expand Down
26 changes: 5 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
#![cfg_attr(feature = "nightly", deny(missing_docs))]
#![cfg_attr(feature = "nightly", feature(external_doc))]
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
#![cfg_attr(test, deny(warnings))]
#![allow(unused_variables)]
#![deny(
nonstandard_style,
rust_2018_idioms,
future_incompatible,
missing_debug_implementations
)]
// TODO: Remove this after clippy bug due to async await is resolved.
// ISSUE: https://github.com/rust-lang/rust-clippy/issues/3988
#![allow(clippy::needless_lifetimes)]
// #![warn(missing_docs)]
#![warn(missing_debug_implementations, rust_2018_idioms)]
#![allow(clippy::mutex_atomic, clippy::module_inception)]
#![doc(test(attr(deny(rust_2018_idioms, warnings))))]
#![doc(test(attr(allow(unused_extern_crates, unused_variables))))]

//!
//! Welcome to Tide.
//!
//! The [`App`](struct.App.html) docs are a good place to get started.
//!
//!

macro_rules! box_async {
{$($t:tt)*} => {
::futures::future::FutureExt::boxed(async move { $($t)* })
};
}

#[macro_use]
pub mod error;

Expand Down
8 changes: 2 additions & 6 deletions src/middleware/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<Data: Send + Sync + 'static> Middleware<Data> for CookiesMiddleware {
mut cx: Context<Data>,
next: Next<'a, Data>,
) -> BoxFuture<'a, Response> {
box_async! {
Box::pin(async move {
let cookie_data = cx
.extensions_mut()
.remove()
Expand All @@ -56,7 +56,7 @@ impl<Data: Send + Sync + 'static> Middleware<Data> for CookiesMiddleware {
}
}
res
}
})
}
}

Expand All @@ -72,23 +72,19 @@ mod tests {
static COOKIE_NAME: &str = "testCookie";

/// Tide will use the the `Cookies`'s `Extract` implementation to build this parameter.
#[allow(unused_mut)] // Workaround clippy bug
async fn retrieve_cookie(mut cx: Context<()>) -> String {
format!("{}", cx.get_cookie(COOKIE_NAME).unwrap().unwrap().value())
}

#[allow(unused_mut)] // Workaround clippy bug
async fn set_cookie(mut cx: Context<()>) {
cx.set_cookie(Cookie::new(COOKIE_NAME, "NewCookieValue"))
.unwrap();
}

#[allow(unused_mut)] // Workaround clippy bug
async fn remove_cookie(mut cx: Context<()>) {
cx.remove_cookie(Cookie::named(COOKIE_NAME)).unwrap();
}

#[allow(unused_mut)] // Workaround clippy bug
async fn set_multiple_cookie(mut cx: Context<()>) {
cx.set_cookie(Cookie::new("C1", "V1")).unwrap();
cx.set_cookie(Cookie::new("C2", "V2")).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions src/middleware/default_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ impl DefaultHeaders {

impl<Data: Send + Sync + 'static> Middleware<Data> for DefaultHeaders {
fn handle<'a>(&'a self, cx: Context<Data>, next: Next<'a, Data>) -> BoxFuture<'a, Response> {
box_async! {
Box::pin(async move {
let mut res = next.run(cx).await;

let headers = res.headers_mut();
for (key, value) in self.headers.iter() {
headers.entry(key).unwrap().or_insert_with(|| value.clone());
}
res
}
})
}
}
Loading