Skip to content

Commit 17600f3

Browse files
authored
Merge pull request #345 from http-rs/page-3
Rewind page 1
2 parents 32cf6a7 + b2bd98c commit 17600f3

File tree

9 files changed

+80
-30
lines changed

9 files changed

+80
-30
lines changed

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@ readme = "README.md"
1919
repository = "https://github.com/http-rs/tide"
2020

2121
[dependencies]
22+
accept-encoding = "0.2.0-alpha.2"
23+
async-compression = "0.1.0-alpha.7"
2224
cookie = { version = "0.12.0", features = ["percent-encode"] }
23-
futures-preview = "0.3.0-alpha.19"
2425
fnv = "1.0.6"
26+
futures-preview = "0.3.0-alpha.19"
2527
http = "0.1.19"
2628
http-service = "0.3.1"
29+
log = "0.4.8"
2730
pin-utils = "0.1.0-alpha.4"
2831
route-recognizer = "0.1.13"
2932
serde = "1.0.102"
3033
serde_derive = "1.0.102"
3134
serde_json = "1.0.41"
35+
serde_qs = "0.5.0"
3236
typemap = "0.3.3"
33-
serde_urlencoded = "0.6.1"
34-
log = "0.4.8"
35-
accept-encoding = "0.2.0-alpha.2"
36-
async-compression = "0.1.0-alpha.7"
3737

3838
[dependencies.http-service-hyper]
3939
optional = true

examples/cookies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use tide::{cookies::ContextExt, middleware::CookiesMiddleware, Context};
33

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

examples/nested_router.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use tide::App;
2+
3+
fn main() {
4+
let mut app = App::new();
5+
app.at("/gates").nest(|router| {
6+
router
7+
.at("/")
8+
.get(|_| async move { "This is an area in front of the gates" });
9+
router.at("/open").get(|_| async move { "Open the gates!" });
10+
router
11+
.at("/close")
12+
.get(|_| async move { "Close the gates!" });
13+
});
14+
app.run("127.0.0.1:8000").unwrap();
15+
}

src/cookies.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl CookieData {
3030
/// An extension to `Context` that provides cached access to cookies
3131
pub trait ContextExt {
3232
/// returns a `Cookie` by name of the cookie
33-
fn get_cookie(&mut self, name: &str) -> Result<Option<Cookie<'static>>, StringError>;
33+
fn get_cookie(&self, name: &str) -> Result<Option<Cookie<'static>>, StringError>;
3434

3535
/// Add cookie to the cookie jar
3636
fn set_cookie(&mut self, cookie: Cookie<'static>) -> Result<(), StringError>;
@@ -41,7 +41,7 @@ pub trait ContextExt {
4141
}
4242

4343
impl<State> ContextExt for Context<State> {
44-
fn get_cookie(&mut self, name: &str) -> Result<Option<Cookie<'static>>, StringError> {
44+
fn get_cookie(&self, name: &str) -> Result<Option<Cookie<'static>>, StringError> {
4545
let cookie_data = self
4646
.extensions()
4747
.get::<CookieData>()

src/forms.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<State: Send + Sync + 'static> ContextExt for Context<State> {
2121
let body = self.take_body();
2222
Box::pin(async move {
2323
let body = body.into_vec().await.client_err()?;
24-
Ok(serde_urlencoded::from_bytes(&body)
24+
Ok(serde_qs::from_bytes(&body)
2525
.map_err(|e| err_fmt!("could not decode form: {}", e))
2626
.client_err()?)
2727
})
@@ -53,8 +53,6 @@ pub fn form<T: serde::Serialize>(t: T) -> Response {
5353
http::Response::builder()
5454
.status(http::status::StatusCode::OK)
5555
.header("Content-Type", "application/x-www-form-urlencoded")
56-
.body(Body::from(
57-
serde_urlencoded::to_string(&t).unwrap().into_bytes(),
58-
))
56+
.body(Body::from(serde_qs::to_string(&t).unwrap().into_bytes()))
5957
.unwrap()
6058
}

src/middleware/cookies.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ mod tests {
7272
static COOKIE_NAME: &str = "testCookie";
7373

7474
/// Tide will use the the `Cookies`'s `Extract` implementation to build this parameter.
75-
async fn retrieve_cookie(mut cx: Context<()>) -> String {
75+
async fn retrieve_cookie(cx: Context<()>) -> String {
7676
format!("{}", cx.get_cookie(COOKIE_NAME).unwrap().unwrap().value())
7777
}
7878

src/middleware/cors.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,12 @@ impl Cors {
149149
impl<State: Send + Sync + 'static> Middleware<State> for Cors {
150150
fn handle<'a>(&'a self, cx: Context<State>, next: Next<'a, State>) -> BoxFuture<'a, Response> {
151151
Box::pin(async move {
152-
let origin = if let Some(origin) = cx.request().headers().get(header::ORIGIN) {
153-
origin.clone()
154-
} else {
155-
return http::Response::builder()
156-
.status(StatusCode::BAD_REQUEST)
157-
.body(Body::empty())
158-
.unwrap();
159-
};
152+
let origin = cx
153+
.request()
154+
.headers()
155+
.get(header::ORIGIN)
156+
.cloned()
157+
.unwrap_or_else(|| HeaderValue::from_static(""));
160158

161159
if !self.is_valid_origin(&origin) {
162160
return http::Response::builder()
@@ -400,7 +398,7 @@ mod test {
400398
let mut server = make_server(app.into_http_service()).unwrap();
401399
let res = server.simulate(request).unwrap();
402400

403-
assert_eq!(res.status(), 400);
401+
assert_eq!(res.status(), 200);
404402
}
405403

406404
#[test]

src/querystring.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ impl<'de, State> ContextExt<'de> for Context<State> {
3131
return Err(Error::from(StatusCode::BAD_REQUEST));
3232
}
3333

34-
Ok(serde_urlencoded::from_str(query.unwrap())
35-
.map_err(|_| Error::from(StatusCode::BAD_REQUEST))?)
34+
Ok(serde_qs::from_str(query.unwrap()).map_err(|_| Error::from(StatusCode::BAD_REQUEST))?)
3635
}
3736
}
3837

src/response.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@ pub type Response = http_service::Response;
44

55
/// Serialize `t` into a JSON-encoded response.
66
pub fn json<T: serde::Serialize>(t: T) -> Response {
7-
// TODO: remove the `unwrap`
8-
http::Response::builder()
9-
.status(http::status::StatusCode::OK)
10-
.header("Content-Type", "application/json")
11-
.body(Body::from(serde_json::to_vec(&t).unwrap()))
12-
.unwrap()
7+
let mut res = http::Response::builder();
8+
match serde_json::to_vec(&t) {
9+
Ok(v) => res
10+
.header("Content-Type", "application/json")
11+
.body(Body::from(v))
12+
.unwrap(),
13+
Err(e) => {
14+
log::error!("{}", e);
15+
res.status(http::status::StatusCode::INTERNAL_SERVER_ERROR)
16+
.body(Body::empty())
17+
.unwrap()
18+
}
19+
}
1320
}
1421

1522
/// A value that is synchronously convertable into a `Response`.
@@ -118,24 +125,57 @@ impl<R: IntoResponse> IntoResponse for WithStatus<R> {
118125
#[cfg(test)]
119126
mod tests {
120127
use super::*;
128+
use futures::executor::block_on;
121129

122130
#[test]
123131
fn test_status() {
124132
let resp = "foo"
125133
.with_status(http::status::StatusCode::NOT_FOUND)
126134
.into_response();
127135
assert_eq!(resp.status(), http::status::StatusCode::NOT_FOUND);
136+
assert_eq!(block_on(resp.into_body().into_vec()).unwrap(), b"foo");
128137
}
129138

130139
#[test]
131140
fn byte_vec_content_type() {
132141
let resp = String::from("foo").into_bytes().into_response();
133142
assert_eq!(resp.headers()["Content-Type"], "application/octet-stream");
143+
assert_eq!(block_on(resp.into_body().into_vec()).unwrap(), b"foo");
134144
}
135145

136146
#[test]
137147
fn string_content_type() {
138148
let resp = String::from("foo").into_response();
139149
assert_eq!(resp.headers()["Content-Type"], "text/plain; charset=utf-8");
150+
assert_eq!(block_on(resp.into_body().into_vec()).unwrap(), b"foo");
151+
}
152+
153+
#[test]
154+
fn json_content_type() {
155+
use std::collections::BTreeMap;
156+
157+
let mut map = BTreeMap::new();
158+
map.insert(Some("a"), 2);
159+
map.insert(Some("b"), 4);
160+
map.insert(None, 6);
161+
162+
let resp = json(map);
163+
assert_eq!(
164+
resp.status(),
165+
http::status::StatusCode::INTERNAL_SERVER_ERROR
166+
);
167+
assert_eq!(block_on(resp.into_body().into_vec()).unwrap(), b"");
168+
169+
let mut map = BTreeMap::new();
170+
map.insert("a", 2);
171+
map.insert("b", 4);
172+
map.insert("c", 6);
173+
174+
let resp = json(map);
175+
assert_eq!(resp.status(), http::status::StatusCode::OK);
176+
assert_eq!(
177+
block_on(resp.into_body().into_vec()).unwrap(),
178+
br##"{"a":2,"b":4,"c":6}"##
179+
);
140180
}
141181
}

0 commit comments

Comments
 (0)