Skip to content

Commit 32cf6a7

Browse files
authored
Merge pull request #344 from http-rs/page2
Rewind page 2
2 parents 333e69d + fc85f20 commit 32cf6a7

25 files changed

+1111
-68
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ serde_json = "1.0.41"
3232
typemap = "0.3.3"
3333
serde_urlencoded = "0.6.1"
3434
log = "0.4.8"
35+
accept-encoding = "0.2.0-alpha.2"
36+
async-compression = "0.1.0-alpha.7"
3537

3638
[dependencies.http-service-hyper]
3739
optional = true

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ and **not ready for production use yet**.
5454
fn main() -> Result<(), std::io::Error> {
5555
let mut app = tide::App::new();
5656
app.at("/").get(|_| async move { "Hello, world!" });
57-
Ok(app.serve("127.0.0.1:8000")?)
57+
Ok(app.run("127.0.0.1:8000")?)
5858
}
5959
```
6060

examples/body_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ fn main() {
4343
app.at("/echo/json").post(echo_json);
4444
app.at("/echo/form").post(echo_form);
4545

46-
app.serve("127.0.0.1:8000").unwrap();
46+
app.run("127.0.0.1:8000").unwrap();
4747
}

examples/catch_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ async fn echo_path(cx: Context<()>) -> String {
88
fn main() {
99
let mut app = tide::App::new();
1010
app.at("/echo_path/*path").get(echo_path);
11-
app.serve("127.0.0.1:8000").unwrap();
11+
app.run("127.0.0.1:8000").unwrap();
1212
}

examples/cookies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ fn main() {
2222
app.at("/").get(retrieve_cookie);
2323
app.at("/set").get(set_cookie);
2424
app.at("/remove").get(remove_cookie);
25-
app.serve("127.0.0.1:8000").unwrap();
25+
app.run("127.0.0.1:8000").unwrap();
2626
}

examples/default_headers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ fn main() {
1111

1212
app.at("/").get(|_| async move { "Hello, world!" });
1313

14-
app.serve("127.0.0.1:8000").unwrap();
14+
app.run("127.0.0.1:8000").unwrap();
1515
}

examples/graphql.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ use juniper::graphql_object;
88
use std::sync::{atomic, Arc};
99
use tide::{error::ResultExt, response, App, Context, EndpointResult};
1010

11-
// First, we define `Data` that holds accumulator state. This is accessible as App data in
11+
// First, we define `State` that holds accumulator state. This is accessible as App data in
1212
// Tide, and as executor context in Juniper.
1313
#[derive(Clone, Default)]
14-
struct Data(Arc<atomic::AtomicIsize>);
14+
struct State(Arc<atomic::AtomicIsize>);
1515

16-
impl juniper::Context for Data {}
16+
impl juniper::Context for State {}
1717

1818
// We define `Query` unit struct here. GraphQL queries will refer to this struct. The struct itself
1919
// doesn't have any associated data (and there's no need to do so), but instead it exposes the
2020
// accumulator state from the context.
2121
struct Query;
2222

23-
graphql_object!(Query: Data |&self| {
23+
graphql_object!(Query: State |&self| {
2424
// GraphQL integers are signed and 32 bits long.
2525
field accumulator(&executor) -> i32 as "Current value of the accumulator" {
2626
executor.context().0.load(atomic::Ordering::Relaxed) as i32
@@ -31,7 +31,7 @@ graphql_object!(Query: Data |&self| {
3131
// `Query`, but it provides the way to "mutate" the accumulator state.
3232
struct Mutation;
3333

34-
graphql_object!(Mutation: Data |&self| {
34+
graphql_object!(Mutation: State |&self| {
3535
field add(&executor, by: i32) -> i32 as "Add given value to the accumulator." {
3636
executor.context().0.fetch_add(by as isize, atomic::Ordering::Relaxed) as i32 + by
3737
}
@@ -43,7 +43,7 @@ type Schema = juniper::RootNode<'static, Query, Mutation>;
4343

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

6060
fn main() {
61-
let mut app = App::with_state(Data::default());
61+
let mut app = App::with_state(State::default());
6262
app.at("/graphql").post(handle_graphql);
63-
app.serve("127.0.0.1:8000").unwrap();
63+
app.run("127.0.0.1:8000").unwrap();
6464
}

examples/hello.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn main() {
22
let mut app = tide::App::new();
33
app.at("/").get(|_| async move { "Hello, world!" });
4-
app.serve("127.0.0.1:8000").unwrap();
4+
app.run("127.0.0.1:8000").unwrap();
55
}

examples/messages.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,5 @@ fn main() {
6666
let mut app = App::with_state(Database::default());
6767
app.at("/message").post(new_message);
6868
app.at("/message/:id").get(get_message).post(set_message);
69-
app.serve("127.0.0.1:8000").unwrap();
69+
app.run("127.0.0.1:8000").unwrap();
7070
}

examples/multipart-form/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ async fn upload_file(mut cx: Context<()>) -> EndpointResult {
5757
fn main() {
5858
let mut app = App::new();
5959
app.at("/upload_file").post(upload_file);
60-
app.serve("127.0.0.1:8000").unwrap();
60+
app.run("127.0.0.1:8000").unwrap();
6161
}
6262

6363
// Test with:

examples/staticfile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,5 @@ async fn handle_path(ctx: Context<StaticFile>) -> EndpointResult {
122122
fn main() {
123123
let mut app = App::with_state(StaticFile::new("./"));
124124
app.at("/*").get(handle_path);
125-
app.serve("127.0.0.1:8000").unwrap();
125+
app.run("127.0.0.1:8000").unwrap();
126126
}

src/app.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ use crate::{
3333
///
3434
/// let mut app = tide::App::new();
3535
/// app.at("/hello").get(|_| async move {"Hello, world!"});
36-
/// app.serve("127.0.0.1:8000").unwrap();
36+
/// app.run("127.0.0.1:8000").unwrap();
3737
/// ```
3838
///
3939
/// # Routing and parameters
4040
///
4141
/// Tide's routing system is simple and similar to many other frameworks. It
42-
/// uses `:foo` for "wildcard" URL segments, and `:foo*` to match the rest of a
42+
/// uses `:foo` for "wildcard" URL segments, and `*foo` to match the rest of a
4343
/// URL (which may include multiple segments). Here's an example using wildcard
4444
/// segments as parameters to endpoints:
4545
///
@@ -64,7 +64,7 @@ use crate::{
6464
/// "Use /hello/{your name} or /goodbye/{your name}"
6565
/// });
6666
///
67-
/// app.serve("127.0.0.1:8000").unwrap();
67+
/// app.run("127.0.0.1:8000").unwrap();
6868
/// ```
6969
///
7070
/// You can learn more about routing in the [`App::at`] documentation.
@@ -119,15 +119,15 @@ use crate::{
119119
/// let mut app = App::with_state(Database::default());
120120
/// app.at("/message").post(new_message);
121121
/// app.at("/message/:id").get(get_message);
122-
/// app.serve("127.0.0.1:8000").unwrap();
122+
/// app.run("127.0.0.1:8000").unwrap();
123123
/// }
124124
/// ```
125125
126126
#[allow(missing_debug_implementations)]
127127
pub struct App<State> {
128128
router: Router<State>,
129129
middleware: Vec<Arc<dyn Middleware<State>>>,
130-
data: State,
130+
state: State,
131131
}
132132

133133
impl App<()> {
@@ -149,7 +149,7 @@ impl<State: Send + Sync + 'static> App<State> {
149149
App {
150150
router: Router::new(),
151151
middleware: Vec::new(),
152-
data: state,
152+
state,
153153
}
154154
}
155155

@@ -176,12 +176,13 @@ impl<State: Send + Sync + 'static> App<State> {
176176
/// parameter called `name`. It is not possible to define wildcard segments
177177
/// with different names for otherwise identical paths.
178178
///
179-
/// Wildcard definitions can be followed by an optional *wildcard
180-
/// modifier*. Currently, there is only one modifier: `*`, which means that
181-
/// the wildcard will match to the end of given path, no matter how many
182-
/// segments are left, even nothing. It is an error to define two wildcard
183-
/// segments with different wildcard modifiers, or to write other path
184-
/// segment after a segment with wildcard modifier.
179+
/// Alternatively a wildcard definitions can start with a `*`, for example
180+
/// `*path`, which means that the wildcard will match to the end of given
181+
/// path, no matter how many segments are left, even nothing.
182+
///
183+
/// The name of the parameter can be omitted to define a path that matches
184+
/// the required structure, but where the parameters are not required.
185+
/// `:` will match a segment, and `*` will match an entire path.
185186
///
186187
/// Here are some examples omitting the HTTP verb based endpoint selection:
187188
///
@@ -190,7 +191,9 @@ impl<State: Send + Sync + 'static> App<State> {
190191
/// app.at("/");
191192
/// app.at("/hello");
192193
/// app.at("add_two/:num");
193-
/// app.at("static/:path*");
194+
/// app.at("files/:user/*");
195+
/// app.at("static/*path");
196+
/// app.at("static/:context/:");
194197
/// ```
195198
///
196199
/// There is no fallback route matching, i.e. either a resource is a full
@@ -222,16 +225,16 @@ impl<State: Send + Sync + 'static> App<State> {
222225
pub fn into_http_service(self) -> Server<State> {
223226
Server {
224227
router: Arc::new(self.router),
225-
data: Arc::new(self.data),
228+
state: Arc::new(self.state),
226229
middleware: Arc::new(self.middleware),
227230
}
228231
}
229232

230-
/// Start serving the app at the given address.
233+
/// Start Running the app at the given address.
231234
///
232235
/// Blocks the calling thread indefinitely.
233236
#[cfg(feature = "hyper")]
234-
pub fn serve(self, addr: impl std::net::ToSocketAddrs) -> std::io::Result<()> {
237+
pub fn run(self, addr: impl std::net::ToSocketAddrs) -> std::io::Result<()> {
235238
let addr = addr
236239
.to_socket_addrs()?
237240
.next()
@@ -241,6 +244,19 @@ impl<State: Send + Sync + 'static> App<State> {
241244
http_service_hyper::run(self.into_http_service(), addr);
242245
Ok(())
243246
}
247+
248+
/// Asynchronously serve the app at the given address.
249+
#[cfg(feature = "hyper")]
250+
pub async fn serve(self, addr: impl std::net::ToSocketAddrs) -> std::io::Result<()> {
251+
// TODO: try handling all addresses
252+
let addr = addr
253+
.to_socket_addrs()?
254+
.next()
255+
.ok_or(std::io::ErrorKind::InvalidInput)?;
256+
257+
let res = http_service_hyper::serve(self.into_http_service(), addr).await;
258+
res.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
259+
}
244260
}
245261

246262
/// An instantiated Tide server.
@@ -251,7 +267,7 @@ impl<State: Send + Sync + 'static> App<State> {
251267
#[allow(missing_debug_implementations)]
252268
pub struct Server<State> {
253269
router: Arc<Router<State>>,
254-
data: Arc<State>,
270+
state: Arc<State>,
255271
middleware: Arc<Vec<Arc<dyn Middleware<State>>>>,
256272
}
257273

@@ -269,12 +285,12 @@ impl<State: Sync + Send + 'static> HttpService for Server<State> {
269285
let method = req.method().to_owned();
270286
let router = self.router.clone();
271287
let middleware = self.middleware.clone();
272-
let data = self.data.clone();
288+
let state = self.state.clone();
273289

274290
Box::pin(async move {
275291
let fut = {
276292
let Selection { endpoint, params } = router.route(&path, method);
277-
let cx = Context::new(data, req, params);
293+
let cx = Context::new(state, req, params);
278294

279295
let next = Next {
280296
endpoint,
@@ -297,19 +313,19 @@ mod tests {
297313
use super::*;
298314
use crate::{middleware::Next, router::Selection, Context, Response};
299315

300-
fn simulate_request<'a, Data: Default + Clone + Send + Sync + 'static>(
301-
app: &'a App<Data>,
316+
fn simulate_request<'a, State: Default + Clone + Send + Sync + 'static>(
317+
app: &'a App<State>,
302318
path: &'a str,
303319
method: http::Method,
304320
) -> BoxFuture<'a, Response> {
305321
let Selection { endpoint, params } = app.router.route(path, method.clone());
306322

307-
let data = Arc::new(Data::default());
323+
let state = Arc::new(State::default());
308324
let req = http::Request::builder()
309325
.method(method)
310326
.body(http_service::Body::empty())
311327
.unwrap();
312-
let cx = Context::new(data, req, params);
328+
let cx = Context::new(state, req, params);
313329
let next = Next {
314330
endpoint,
315331
next_middleware: &app.middleware,

src/context.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use http_service::Body;
33
use route_recognizer::Params;
44
use std::{str::FromStr, sync::Arc};
55

6-
/// Data associated with a request-response lifecycle.
6+
/// State associated with a request-response lifecycle.
77
///
88
/// The `Context` gives endpoints access to basic information about the incoming
99
/// request, route parameters, and various ways of accessing the request's body.
@@ -55,7 +55,12 @@ impl<State> Context<State> {
5555
&self.request
5656
}
5757

58-
/// Access app-global data.
58+
/// Access a mutable handle to the entire request.
59+
pub fn request_mut(&mut self) -> &mut http_service::Request {
60+
&mut self.request
61+
}
62+
63+
/// Access app-global state.
5964
pub fn state(&self) -> &State {
6065
&self.state
6166
}

src/endpoint.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{response::IntoResponse, Context, Response};
2626
/// fn main() {
2727
/// let mut app = tide::App::new();
2828
/// app.at("/hello").get(hello);
29-
/// app.serve("127.0.0.1:8000").unwrap()
29+
/// app.run("127.0.0.1:8000").unwrap()
3030
/// }
3131
/// ```
3232
///
@@ -41,7 +41,7 @@ use crate::{response::IntoResponse, Context, Response};
4141
/// fn main() {
4242
/// let mut app = tide::App::new();
4343
/// app.at("/hello").get(hello);
44-
/// app.serve("127.0.0.1:8000").unwrap()
44+
/// app.run("127.0.0.1:8000").unwrap()
4545
/// }
4646
/// ```
4747
///

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
//! Welcome to Tide.
88
//!
99
//! The [`App`](struct.App.html) docs are a good place to get started.
10-
//!
11-
//!
1210
1311
#[macro_use]
1412
pub mod error;

0 commit comments

Comments
 (0)