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とセッションのチェックはライブラリ側で行いたい