get methodもhashmapではなく、HttpResponseに変更することで、get methodでもcookieをセットできるようになる。
use std::collections::HashMap; mod ares; use ares::{Router, HttpResponse, parse, signup, logup, redirect, render_template_from_file, render_template_from_file_empty}; fn main() { let mut router = Router::new(); router.get("index", handle_index); router.get("hello", handle_hello); router.post("test", handle_test); router.get("signin", handle_signin); router.post("signup", handle_signup); router.get("login", handle_login); router.post("logup", handle_logup); router.get("logout", handle_logout); let needs_auth = Some(vec!["/index", "/hello"]); router.up("192.168.33.10:8000", needs_auth); } fn handle_index() -> HttpResponse { let mut content = HashMap::new(); content.insert( "title", "This is index page!", ); let html = render_template_from_file("index", &content); HttpResponse::new(200, &html) } fn handle_hello() -> HttpResponse { let mut data = HashMap::new(); data.insert("name", "taro"); let html = render_template_from_file("hello", &data); HttpResponse::new(200, &html) } fn handle_signin() -> HttpResponse { let html = render_template_from_file_empty("signin"); HttpResponse::new(200, &html) } fn handle_signup(body: String) -> HttpResponse { let form = parse(&body); let binding = "<unknown>".to_string(); let name = form.get("name").unwrap_or(&binding); let password = form.get("password").unwrap_or(&binding); let _csrf_token = form.get("csrf_token").unwrap_or(&"".to_string()); let redirect_path = "/index"; signup(name, password, redirect_path) } fn handle_login() -> HttpResponse { let html = render_template_from_file_empty("login"); HttpResponse::new(200, &html) } fn handle_logup(body: String) -> HttpResponse { let form = parse(&body); let binding = "<unknown>".to_string(); let name = form.get("name").unwrap_or(&binding); let password = form.get("password").unwrap_or(&binding); let login_success_path = "/index"; let login_failure_path = "/login"; logup(name, password, login_success_path, login_failure_path) } fn handle_test(_body: String) -> HttpResponse { redirect("/index"); HttpResponse::new(200, "<h1>This is Test!</h1>") } fn handle_logout() -> HttpResponse { let html = render_template_from_file_empty("logout"); HttpResponse::new(200, &html) }
以下のようにする
fn handle_login() -> HttpResponse { let (csrf_token, mut response) = create_csrf_token(); let mut context = HashMap::new(); context.insert("csrf_token", csrf_token); let html = render_template_from_file("login", &context); response.body = html; response }
pub fn create_csrf_token() -> (&'static str, HttpResponse) { let (session_token, csrf_token) = create_session_token_and_csrf(); if let Ok(mut client) = psql_connect() { let _ = client.execute( "INSERT INTO ares_sessions (session_token, csrf_token) VALUES ($1, $2)", &[&session_token, &csrf_token], ); } let mut response = HttpResponse::new(200, ""); response.headers.insert( "Set-Cookie".to_string(), format!("session_token={}; Path=/; HttpOnly", session_token), ); let csrf_token_leaked = Box::leak(csrf_token.into_boxed_str()); (csrf_token_leaked, response) }
CSRFとセッションのチェックはライブラリ側で行いたい