Skip to content
This repository has been archived by the owner on Oct 29, 2021. It is now read-only.

Commit

Permalink
feat: impl cookie parser
Browse files Browse the repository at this point in the history
Implement cookie parser middleware. Enable context cookie getter. Fix
context dynamic data get and get_mut return wrong type issue.
  • Loading branch information
plwai committed Feb 11, 2020
1 parent fa22615 commit 4548009
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 139 deletions.
256 changes: 121 additions & 135 deletions examples/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{fmt, fmt::Display};
use obsidian::{
context::Context,
cookie::Cookie,
middleware::logger::Logger,
middleware::{cookie_parser::CookieParser, logger::Logger},
router::{header, Responder, Response, Router},
App, StatusCode,
};
Expand Down Expand Up @@ -81,169 +81,154 @@ async fn main() {
Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut icon\" href=\"favicon.ico\" type=\"image/x-icon\" sizes=\"32x32\" /></head> <h1>Hello Obsidian</h1></html>")
});

app.get("/json", |_ctx| {
async {
let point = Point { x: 1, y: 2 };
app.get("/json", |_ctx| async {
let point = Point { x: 1, y: 2 };

Response::created()
.set_header(header::AUTHORIZATION, "token")
.set_header_str("X-Custom-Header", "Custom header value")
.json(point)
}
Response::created()
.set_header(header::AUTHORIZATION, "token")
.set_header_str("X-Custom-Header", "Custom header value")
.json(point)
});

app.get("/json-with-headers", |_ctx| {
async {
let point = Point { x: 1, y: 2 };

let custom_headers = vec![
("X-Custom-Header-1", "Custom header 1"),
("X-Custom-Header-2", "Custom header 2"),
("X-Custom-Header-3", "Custom header 3"),
];

let standard_headers = vec![
(header::AUTHORIZATION, "token"),
(header::ACCEPT_CHARSET, "utf-8"),
];

Response::created()
.with_headers(standard_headers)
.with_headers_str(custom_headers)
.json(point)
}
app.get("/json-with-headers", |_ctx| async {
let point = Point { x: 1, y: 2 };

let custom_headers = vec![
("X-Custom-Header-1", "Custom header 1"),
("X-Custom-Header-2", "Custom header 2"),
("X-Custom-Header-3", "Custom header 3"),
];

let standard_headers = vec![
(header::AUTHORIZATION, "token"),
(header::ACCEPT_CHARSET, "utf-8"),
];

Response::created()
.with_headers(standard_headers)
.with_headers_str(custom_headers)
.json(point)
});

app.get("/string-with-headers", |_ctx| {
async {
let custom_headers = vec![
("X-Custom-Header-1", "Custom header 1"),
("X-Custom-Header-2", "Custom header 2"),
("X-Custom-Header-3", "Custom header 3"),
];

let standard_headers = vec![
(header::AUTHORIZATION, "token"),
(header::ACCEPT_CHARSET, "utf-8"),
];

"Hello World"
.with_headers(standard_headers)
.with_headers_str(custom_headers)
}
app.get("/string-with-headers", |_ctx| async {
let custom_headers = vec![
("X-Custom-Header-1", "Custom header 1"),
("X-Custom-Header-2", "Custom header 2"),
("X-Custom-Header-3", "Custom header 3"),
];

let standard_headers = vec![
(header::AUTHORIZATION, "token"),
(header::ACCEPT_CHARSET, "utf-8"),
];

"Hello World"
.with_headers(standard_headers)
.with_headers_str(custom_headers)
});

app.get("/string-with-cookie", |_ctx| {
async {
"Hello World"
.with_cookie(Cookie::new("username", "plwai"))
.with_cookie(Cookie::new("session-id", "123456"))
.with_cookie_raw("content=raw; HttpOnly")
}
app.get("/string-with-cookie", |_ctx| async {
"Hello World"
.with_cookie(Cookie::new("username", "john"))
.with_cookie(Cookie::new("session-id", "123456"))
.with_cookie_raw("content=raw; HttpOnly")
});

app.get("/string-with-cookies", |_ctx| async {
let cookies = vec![
Cookie::new("bulk-cookie-1", "cookie-1"),
Cookie::new("bulk-cookie-2", "cookie-2"),
Cookie::build("bulk-cookie-3", "cookie-3")
.same_site(cookie::SameSite::Strict)
.http_only(true)
.finish(),
];

"Hello World".with_cookies(cookies)
});

app.get("/string-with-cookies", |_ctx| {
async {
let cookies = vec![
Cookie::new("bulk-cookie-1", "cookie-1"),
Cookie::new("bulk-cookie-2", "cookie-2"),
Cookie::build("bulk-cookie-3", "cookie-3")
.same_site(cookie::SameSite::Strict)
.http_only(true)
.finish(),
];

"Hello World".with_cookies(cookies)
app.get("/request-with-cookie", |ctx: Context| async move {
match ctx.cookie("username") {
Some(cookie) => cookie.to_string(),
None => "No cookie".to_string(),
}
});

app.get("/empty-body", |_ctx| async { StatusCode::OK });

app.get("/vec", |_ctx| {
async { vec![1, 2, 3].with_status(StatusCode::CREATED) }
app.get("/vec", |_ctx| async {
vec![1, 2, 3].with_status(StatusCode::CREATED)
});

app.get("/String", |_ctx| {
async { "<h1>This is a String</h1>".to_string() }
app.get("/String", |_ctx| async {
"<h1>This is a String</h1>".to_string()
});

app.get("/test/radix", |_ctx| {
async { "<h1>Test radix</h1>".to_string() }
app.get("/test/radix", |_ctx| async {
"<h1>Test radix</h1>".to_string()
});

app.get("/team/radix", |_ctx| async { "Team radix".to_string() });

app.get("/test/radix2", |_ctx| {
async { "<h1>Test radix2</h1>".to_string() }
app.get("/test/radix2", |_ctx| async {
"<h1>Test radix2</h1>".to_string()
});

app.get("/jsontest", |_ctx| {
async { Response::ok().file("./testjson.html").await }
app.get("/jsontest", |_ctx| async {
Response::ok().file("./testjson.html").await
});

app.get("/jsan", |_ctx: Context| {
async { "<h1>jsan</h1>".to_string() }
app.get("/jsan", |_ctx: Context| async {
"<h1>jsan</h1>".to_string()
});

app.get("/test/wildcard/*", |ctx: Context| {
async move {
format!(
"{}<br>{}",
"<h1>Test wildcard</h1>".to_string(),
ctx.uri().path()
)
}
app.get("/test/wildcard/*", |ctx: Context| async move {
format!(
"{}<br>{}",
"<h1>Test wildcard</h1>".to_string(),
ctx.uri().path()
)
});

app.get("router/test", |ctx: Context| {
async move {
let result = ctx.extensions().get::<LoggerExampleData>()?;
app.get("router/test", |ctx: Context| async move {
let result = ctx.extensions().get::<LoggerExampleData>()?;

dbg!(&result.0);
dbg!(&result.0);

Some(format!(
"{}<br>{}",
"<h1>router test get</h1>".to_string(),
ctx.uri().path()
))
}
Some(format!(
"{}<br>{}",
"<h1>router test get</h1>".to_string(),
ctx.uri().path()
))
});
app.post("router/test", |ctx: Context| {
async move {
format!(
"{}<br>{}",
"<h1>router test post</h1>".to_string(),
ctx.uri().path()
)
}
app.post("router/test", |ctx: Context| async move {
format!(
"{}<br>{}",
"<h1>router test post</h1>".to_string(),
ctx.uri().path()
)
});
app.put("router/test", |ctx: Context| {
async move {
format!(
"{}<br>{}",
"<h1>router test put</h1>".to_string(),
ctx.uri().path()
)
}
app.put("router/test", |ctx: Context| async move {
format!(
"{}<br>{}",
"<h1>router test put</h1>".to_string(),
ctx.uri().path()
)
});
app.delete("router/test", |ctx: Context| {
async move {
format!(
"{}<br>{}",
"<h1>router test delete</h1>".to_string(),
ctx.uri().path()
)
}
app.delete("router/test", |ctx: Context| async move {
format!(
"{}<br>{}",
"<h1>router test delete</h1>".to_string(),
ctx.uri().path()
)
});

app.get("route/diff_route", |ctx: Context| {
async move {
format!(
"{}<br>{}",
"<h1>route diff get</h1>".to_string(),
ctx.uri().path()
)
}
app.get("route/diff_route", |ctx: Context| async move {
format!(
"{}<br>{}",
"<h1>route diff get</h1>".to_string(),
ctx.uri().path()
)
});

let mut form_router = Router::new();
Expand All @@ -262,6 +247,9 @@ Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut icon\" href=
let logger = Logger::new();
app.use_service(logger);

let cookie_parser = CookieParser::new();
app.use_service(cookie_parser);

// param_router.get("/paramtest/:id", |ctx: Context| async move {
// let param_test: i32 = ctx.param("id")?;

Expand All @@ -282,16 +270,14 @@ Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut icon\" href=
let logger_example = middleware::logger_example::LoggerExample::new();
app.use_service(logger_example);

param_router.get("/test-next-wild/*", |_ctx| {
async { "<h1>test next wild</h1>".to_string() }
param_router.get("/test-next-wild/*", |_ctx| async {
"<h1>test next wild</h1>".to_string()
});

param_router.get("/*", |_ctx| {
async {
"<h1>404 Not Found</h1>"
.to_string()
.with_status(StatusCode::NOT_FOUND)
}
param_router.get("/*", |_ctx| async {
"<h1>404 Not Found</h1>"
.to_string()
.with_status(StatusCode::NOT_FOUND)
});

app.use_router("/params/", param_router);
Expand Down
20 changes: 16 additions & 4 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use cookie::Cookie;
use http::Extensions;
use hyper::{body, body::Buf};
use serde::de::DeserializeOwned;
Expand All @@ -8,6 +9,7 @@ use std::collections::HashMap;
use std::convert::From;
use std::str::FromStr;

use crate::middleware::cookie_parser::CookieParserData;
use crate::router::from_cow_map;
use crate::ObsidianError;
use crate::{header::HeaderValue, Body, HeaderMap, Method, Request, Uri};
Expand Down Expand Up @@ -64,13 +66,13 @@ impl Context {
}

/// Get dynamic data from request extensions
pub fn get<T: Send + Sync + 'static>(&mut self) {
self.extensions().get::<T>();
pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
self.extensions().get::<T>()
}

/// Get mutable dynamic data from request extensions
pub fn get_mut<T: Send + Sync + 'static>(&mut self) {
self.extensions_mut().get_mut::<T>();
pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
self.extensions_mut().get_mut::<T>()
}

/// Method to get the params value according to key.
Expand Down Expand Up @@ -269,6 +271,16 @@ impl Context {
unimplemented!()
}

pub fn cookie(&self, name: &str) -> Option<&Cookie> {
if let Some(cookie_data) = self.get::<CookieParserData>() {
if let Some(ref cookie) = cookie_data.cookie_jar().get(name) {
return Some(*cookie);
}
}

None
}

/// Consumes body of the request and replace it with empty body.
pub fn take_body(&mut self) -> Body {
std::mem::replace(self.request.body_mut(), Body::empty())
Expand Down
1 change: 1 addition & 0 deletions src/middleware.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod cookie_parser;
pub mod logger;

use async_trait::async_trait;
Expand Down
Loading

0 comments on commit 4548009

Please sign in to comment.