Skip to content

Refactor API #350

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 65 commits into from
Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
36f253a
rename Server to Service & App::serve to App::listen
yoshuawuyts Nov 4, 2019
dd0adb5
rename App to Server
yoshuawuyts Nov 4, 2019
837d536
update example
yoshuawuyts Nov 4, 2019
5f06355
s/Context/Request/
yoshuawuyts Nov 4, 2019
300ad71
rename Context to Request, and submodule Route
yoshuawuyts Nov 4, 2019
770ede7
server docs
yoshuawuyts Nov 4, 2019
5a2bbd5
rename EndpointResult to Result
yoshuawuyts Nov 4, 2019
2cca096
remove err_fmt macro
yoshuawuyts Nov 4, 2019
77d4769
remove fnv
yoshuawuyts Nov 4, 2019
3ba6850
remove typemap
yoshuawuyts Nov 4, 2019
5415e68
rm pin-utils
yoshuawuyts Nov 4, 2019
b86789d
remove serde_derive
yoshuawuyts Nov 4, 2019
bae9367
cleanup more deps
yoshuawuyts Nov 4, 2019
d9eef1f
intro docs
yoshuawuyts Nov 4, 2019
c0d5783
Disable multipart
yoshuawuyts Nov 4, 2019
b0f1fe6
fix tests
yoshuawuyts Nov 4, 2019
e15dcca
hid more imports
yoshuawuyts Nov 4, 2019
908ee03
cleanup type docs
yoshuawuyts Nov 4, 2019
c6e3e36
restructure response file
yoshuawuyts Nov 4, 2019
3aea1d9
init Response refactor, add Body
yoshuawuyts Nov 4, 2019
f073c81
update middleware
yoshuawuyts Nov 4, 2019
8d3cc9e
finish body type
yoshuawuyts Nov 4, 2019
b406602
docs
yoshuawuyts Nov 4, 2019
793605e
temp fix warnings
yoshuawuyts Nov 4, 2019
44af829
rework body
yoshuawuyts Nov 4, 2019
1f67e78
separate querystring test
yoshuawuyts Nov 4, 2019
f8a804a
squash querystring, move context.rs -> request.rs
yoshuawuyts Nov 4, 2019
1b8a5d9
integrate forms into req/res
yoshuawuyts Nov 4, 2019
8f0cc8c
remove BoxTryError + fix compile error
yoshuawuyts Nov 4, 2019
c176241
cargo fmt + docs
yoshuawuyts Nov 4, 2019
519fab4
disable serde derives
yoshuawuyts Nov 4, 2019
741565a
use async-std
yoshuawuyts Nov 4, 2019
e74f400
remove run
yoshuawuyts Nov 4, 2019
7ce86f2
remove request from Request
yoshuawuyts Nov 4, 2019
a40da1a
wip
yoshuawuyts Nov 5, 2019
0048e35
use new http-service
yoshuawuyts Nov 7, 2019
fa82a3b
return string
yoshuawuyts Nov 7, 2019
010cbbc
compiles!
yoshuawuyts Nov 7, 2019
f68462b
write test
yoshuawuyts Nov 7, 2019
f0432a3
responses work!
yoshuawuyts Nov 8, 2019
c34d63e
echo server example in docs
yoshuawuyts Nov 8, 2019
f366b14
json ser/de
yoshuawuyts Nov 8, 2019
63bea39
Response::ok
yoshuawuyts Nov 8, 2019
b21b67f
Response::with_reader
yoshuawuyts Nov 8, 2019
5096627
remove Response::ok
yoshuawuyts Nov 8, 2019
2676080
stability notice
yoshuawuyts Nov 8, 2019
11db3c7
update hello example
yoshuawuyts Nov 8, 2019
2beed90
fewer build deps + all mods public
yoshuawuyts Nov 10, 2019
4bb8028
export parity with Surf
yoshuawuyts Nov 10, 2019
c2c4054
prelude + public ResponseExt
yoshuawuyts Nov 10, 2019
afc3a60
result types
yoshuawuyts Nov 10, 2019
e22138a
no clippy
yoshuawuyts Nov 10, 2019
bb015de
comment out tests
yoshuawuyts Nov 11, 2019
4aec5fe
backup examples
yoshuawuyts Nov 11, 2019
1c886eb
all tests pass
yoshuawuyts Nov 11, 2019
be72c13
fix find-replace artifacts
yoshuawuyts Nov 19, 2019
496ab9c
future 0.3
yoshuawuyts Nov 20, 2019
2e2a193
add get/set local
yoshuawuyts Nov 20, 2019
eb57bcb
readme cleanup
yoshuawuyts Nov 20, 2019
ca52897
add changelog
yoshuawuyts Nov 26, 2019
a30b6da
move middleware around
yoshuawuyts Nov 26, 2019
952052a
update deps
yoshuawuyts Nov 27, 2019
e9c7511
cargo fmt
yoshuawuyts Nov 27, 2019
6304431
Remove unneeded imports and don't use select
skade Nov 27, 2019
83eb00a
Merge pull request #359 from skade/tiny-fixes
yoshuawuyts Nov 27, 2019
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
12 changes: 0 additions & 12 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,3 @@ jobs:

- name: Docs
run: cargo doc

clippy_check:
name: Clippy check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install rust
run: rustup update stable && rustup default stable
- name: Install clippy
run: rustup component add clippy
- name: clippy
run: cargo clippy --all
56 changes: 51 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,63 @@ and this project adheres to [Semantic Versioning](https://book.async.rs/overview

## [Unreleased]

## [0.4.0] - 2019-11-26

This release is a further polishing of Tide's APIs, and works towards
significantly improving Tide's user experience. The biggest question left
unanswered after this patch is how we want to do error handling, but aside from
that the end-user API should be pretty close to where we want it to be.

The biggest changes in this patch is endpoints now take `Request` instead of
`Context`. The new `Request` and `Response` types are no longer type aliases but
concrete types, making them substantially easier to use. This also means that
we've been able to fold in all the `Ext` methods we were exposing, enabling
methods such as `let values: Schema = req.body_json()?;` to deserialize an
incoming JSON body through a `Serde` schema. This should make it significantly
easier to write APIs with Tide out of the box.

## Example

```rust
use async_std::task;

fn main() -> Result<(), std::io::Error> {
task::block_on(async {
let mut app = tide::new();
app.at("/").get(|_| async move { "Hello, world!" });
app.listen("127.0.0.1:8080").await?;
Ok(())
})
}
```

### Added

- Added `logger::RequestLogger` based on `log` (replaces `logger:RootLogger`)
- Added `logger::RequestLogger` based on `log` (replaces `logger:RootLogger`).
- Added `Request` with inherent methods (replaces `Context`).
- Added `Server` (replaces `App`).
- Added `Response` (replacing a type alias of the same name).
- Added a `prelude` submodule, holding all public traits.
- Added a `new` free function, a shorthand for `Server::new`.
- Added a `with_state` free function, a shorthand for `Server::with_state`.
- Added `Result` type alias (replaces `EndpointResult`).

### Changed

- Resolved an `#[allow(unused_mut)]` workaround.
- Renamed `ExtractForms` to `ContextExt`.
- `Response` is now a newly defined type.

### Removed

- Removed `logger::RootLogger` (replaced by `logger:RequestLogger`)
- Removed internal use of the `box_async` macro
- Removed `logger::RootLogger` (replaced by `logger:RequestLogger`).
- Removed internal use of the `box_async` macro.
- Removed `Context` (replaced by `Request`).
- Removed the `Response` type alias (replaced by a new `Response` struct).
- Removed `App` (replaced by `Server`).
- Temporarily disabled the multipart family of APIs, improving compilation
speed by ~30%.
- Removed `EndpointResult` (replaced by `Result`).

## [0.3.0] - 2019-10-31

Expand All @@ -34,7 +78,9 @@ were right before splitting up the crate. This release is mostly similar to
- Added keywords and categories to Cargo.toml.
- Implemented `Default` for `App`.
- Added `App::with_state` constructor method.
- Added `Context::state` (replacing `Context::app_data`)
- Added `Context::state` (replacing `Request::app_data`)
- Added examples to the documentation root.
- Added a section about stability guarantees to the documentation root.

### Changed

Expand All @@ -53,7 +99,7 @@ were right before splitting up the crate. This release is mostly similar to
- Removed an extra incoming license requirement.
- Removed outdated version logs.
- Removed `rustfmt.toml`.
- Removed `Context::app_data` (replaced with `Context::state`).
- Removed `Request::app_data` (replaced with `Context::state`).

## [0.2.0] - 2019-05-03

Expand Down
44 changes: 15 additions & 29 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,54 +18,40 @@ license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/http-rs/tide"

[features]
default = ["hyper-server"]
hyper-server = ["http-service-hyper"]
unstable = []

[dependencies]
accept-encoding = "0.2.0-alpha.2"
cookie = { version = "0.12.0", features = ["percent-encode"] }
fnv = "1.0.6"
futures = "0.3.1"
http = "0.1.19"
http-service = "0.3.1"
http-service = "0.4.0"
http-service-hyper = { version = "0.4.1", optional = true }
log = "0.4.8"
pin-utils = "0.1.0-alpha.4"
route-recognizer = "0.1.13"
serde = "1.0.102"
serde_derive = "1.0.102"
serde_json = "1.0.41"
serde_qs = "0.5.0"
typemap = "0.3.3"

[dependencies.async-compression]
version = "0.1.0"
features = ["stream", "all-algorithms"]

[dependencies.http-service-hyper]
optional = true
version = "0.3.1"

[dependencies.multipart]
default-features = false
features = ["server"]
version = "0.16.1"

[features]
default = ["hyper"]
hyper = ["http-service-hyper"]
unstable = []
async-std = { version = "1.0.1", features = ["unstable"] }
hyper = { version = "0.12.35", default-features = false }
bytes = "0.4.12"
anyhow = "1.0.19"
pin-project-lite = "0.1.0"
mime = "0.3.14"

[dev-dependencies]
basic-cookies = "0.1.3"
bytes = "0.4.12"
futures-fs = "0.0.5"
futures-util = { version = "0.3.0", features = ["compat"] }
http-service-mock = "0.3.1"
http-service-mock = "0.4.0"
juniper = "0.14.1"
mime = "0.3.14"
mime_guess = "2.0.1"
percent-encoding = "2.1.0"
serde = { version = "1.0.102", features = ["derive"] }
structopt = "0.3.3"

[patch.crates-io]
http-service = { git = "https://github.com/http-rs/http-service.git" }
http-service-mock = { git = "https://github.com/http-rs/http-service.git" }
http-service-hyper = { git = "https://github.com/http-rs/http-service.git" }
surf = "1.0.3"
19 changes: 4 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,20 @@
</div>

A modular web framework built around async/await. It's actively being developed
and **not ready for production use yet**.
and **not ready for production yet**.

## Examples

**Hello World**

```rust
fn main() -> Result<(), std::io::Error> {
let mut app = tide::App::new();
let mut app = tide::Server::new();
app.at("/").get(|_| async move { "Hello, world!" });
Ok(app.run("127.0.0.1:8000")?)
}
```

**More Examples**

- [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:
Expand All @@ -87,8 +76,8 @@ 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/http-rs/tide/blob/master/.github/CODE_OF_CONDUCT.md). This
describes the minimum behavior expected from all contributors.
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 Down
14 changes: 7 additions & 7 deletions examples/body_types.rs → backup/examples/body_types.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use serde::{Deserialize, Serialize};
use tide::{
error::ResultExt,
forms::{self, ContextExt},
response, App, Context, EndpointResult,
forms::{self, RequestExt},
response, Request, Result, Server,
};

#[derive(Serialize, Deserialize, Clone, Debug)]
Expand All @@ -11,32 +11,32 @@ struct Message {
contents: String,
}

async fn echo_string(mut cx: Context<()>) -> String {
async fn echo_string(mut cx: Request<()>) -> String {
let msg = cx.body_string().await.unwrap();
println!("String: {}", msg);
msg
}

async fn echo_bytes(mut cx: Context<()>) -> Vec<u8> {
async fn echo_bytes(mut cx: Request<()>) -> Vec<u8> {
let msg = cx.body_bytes().await.unwrap();
println!("Bytes: {:?}", msg);
msg
}

async fn echo_json(mut cx: Context<()>) -> EndpointResult {
async fn echo_json(mut cx: Request<()>) -> Result {
let msg = cx.body_json().await.client_err()?;
println!("JSON: {:?}", msg);
Ok(response::json(msg))
}

async fn echo_form(mut cx: Context<()>) -> EndpointResult {
async fn echo_form(mut cx: Request<()>) -> Result {
let msg = cx.body_form().await?;
println!("Form: {:?}", msg);
Ok(forms::form(msg))
}

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

app.at("/echo/string").post(echo_string);
app.at("/echo/bytes").post(echo_bytes);
Expand Down
6 changes: 3 additions & 3 deletions examples/catch_all.rs → backup/examples/catch_all.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use tide::Context;
use tide::Request;

async fn echo_path(cx: Context<()>) -> String {
async fn echo_path(cx: Request<()>) -> String {
let path: String = cx.param("path").unwrap();
format!("Your path is: {}", path)
}

fn main() {
let mut app = tide::App::new();
let mut app = tide::Server::new();
app.at("/echo_path/*path").get(echo_path);
app.run("127.0.0.1:8000").unwrap();
}
10 changes: 5 additions & 5 deletions examples/cookies.rs → backup/examples/cookies.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use cookie::Cookie;
use tide::{cookies::ContextExt, middleware::CookiesMiddleware, Context};
use tide::{cookies::RequestExt, middleware::CookiesMiddleware, Request};

/// Tide will use the the `Cookies`'s `Extract` implementation to build this parameter.
///
async fn retrieve_cookie(cx: Context<()>) -> String {
async fn retrieve_cookie(cx: Request<()>) -> String {
format!("hello cookies: {:?}", cx.get_cookie("hello").unwrap())
}

async fn set_cookie(mut cx: Context<()>) {
async fn set_cookie(mut cx: Request<()>) {
cx.set_cookie(Cookie::new("hello", "world")).unwrap();
}

async fn remove_cookie(mut cx: Context<()>) {
async fn remove_cookie(mut cx: Request<()>) {
cx.remove_cookie(Cookie::named("hello")).unwrap();
}

fn main() {
let mut app = tide::App::new();
let mut app = tide::Server::new();
app.middleware(CookiesMiddleware::new());

app.at("/").get(retrieve_cookie);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use tide::middleware::DefaultHeaders;

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

app.middleware(
DefaultHeaders::new()
Expand Down
8 changes: 4 additions & 4 deletions examples/graphql.rs → backup/examples/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
use http::status::StatusCode;
use juniper::graphql_object;
use std::sync::{atomic, Arc};
use tide::{error::ResultExt, response, App, Context, EndpointResult};
use tide::{error::ResultExt, response, Request, Result, Server};

// First, we define `State` that holds accumulator state. This is accessible as App data in
// First, we define `State` that holds accumulator state. This is accessible as Server data in
// Tide, and as executor context in Juniper.
#[derive(Clone, Default)]
struct State(Arc<atomic::AtomicIsize>);
Expand Down Expand Up @@ -43,7 +43,7 @@ type Schema = juniper::RootNode<'static, Query, Mutation>;

// Finally, we'll bridge between Tide and Juniper. `GraphQLRequest` from Juniper implements
// `Deserialize`, so we use `Json` extractor to deserialize the request body.
async fn handle_graphql(mut cx: Context<State>) -> EndpointResult {
async fn handle_graphql(mut cx: Request<State>) -> Result {
let query: juniper::http::GraphQLRequest = cx.body_json().await.client_err()?;
let schema = Schema::new(Query, Mutation);
let response = query.execute(&schema, cx.state());
Expand All @@ -58,7 +58,7 @@ async fn handle_graphql(mut cx: Context<State>) -> EndpointResult {
}

fn main() {
let mut app = App::with_state(State::default());
let mut app = Server::with_state(State::default());
app.at("/graphql").post(handle_graphql);
app.run("127.0.0.1:8000").unwrap();
}
10 changes: 5 additions & 5 deletions examples/messages.rs → backup/examples/messages.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use http::status::StatusCode;
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
use tide::{error::ResultExt, response, App, Context, EndpointResult};
use tide::{error::ResultExt, response, Request, Result, Server};

#[derive(Default)]
struct Database {
Expand Down Expand Up @@ -37,12 +37,12 @@ impl Database {
}
}

async fn new_message(mut cx: Context<Database>) -> EndpointResult<String> {
async fn new_message(mut cx: Request<Database>) -> Result<String> {
let msg = cx.body_json().await.client_err()?;
Ok(cx.state().insert(msg).to_string())
}

async fn set_message(mut cx: Context<Database>) -> EndpointResult<()> {
async fn set_message(mut cx: Request<Database>) -> Result<()> {
let msg = cx.body_json().await.client_err()?;
let id = cx.param("id").client_err()?;

Expand All @@ -53,7 +53,7 @@ async fn set_message(mut cx: Context<Database>) -> EndpointResult<()> {
}
}

async fn get_message(cx: Context<Database>) -> EndpointResult {
async fn get_message(cx: Request<Database>) -> Result {
let id = cx.param("id").client_err()?;
if let Some(msg) = cx.state().get(id) {
Ok(response::json(msg))
Expand All @@ -63,7 +63,7 @@ async fn get_message(cx: Context<Database>) -> EndpointResult {
}

fn main() {
let mut app = App::with_state(Database::default());
let mut app = Server::with_state(Database::default());
app.at("/message").post(new_message);
app.at("/message/:id").get(get_message).post(set_message);
app.run("127.0.0.1:8000").unwrap();
Expand Down
Loading