program
rust
axum
从请求中获取 cookie

从请求中获取 cookie

在Axum中获取请求中的cookieidtoken等信息,可以通过axum::extract::CookieJar来实现。以下是一个示例代码:

use axum::{
    extract::{CookieJar, Path},
    response::IntoResponse,
    Router,
};
use std::net::SocketAddr;
 
async fn handle_request(CookieJar(cookies): CookieJar, Path(path_param): Path<String>) -> impl IntoResponse {
    // 从Cookie中获取id,如果不存在则返回None
    let id = cookies.get("id");
    // 从Cookie中获取token,如果不存在则返回None
    let token = cookies.get("token");
 
    let response_message = if let (Some(id), Some(token)) = (id, token) {
        format!("Received path parameter: {}, Cookie id: {}, Cookie token: {}", path_param, id.value(), token.value())
    } else {
        format!("Received path parameter: {}, Cookie id or token not found", path_param)
    };
 
    response_message
}
 
#[tokio::main]
async fn main() {
    let app = Router::new()
      .route("/api/endpoint/{path_param}", axum::routing::get(handle_request));
 
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
      .serve(app.into_make_service())
      .await
      .unwrap();
}

在上述代码中:

  • handle_request函数中,通过CookieJar提取器从请求中提取出CookieJar
  • 然后使用cookies.get("id")cookies.get("token")分别尝试获取名为idtokenCookie。如果Cookie存在,就可以通过value()方法获取其值。
  • 这里还结合了路径参数的提取(通过Path提取器),以便在响应消息中同时包含路径参数以及从Cookie中获取到的信息。

请注意,实际应用中,要确保客户端在发送请求时确实设置了对应的Cookie,否则获取到的值将为None

设置 cookie

  1. 使用axum - extra库设置Cookie
    • 首先,需要在Cargo.toml中添加axum - extra依赖:
    axum-extra = "0.6.0"
    • 以下是一个设置Cookie的示例代码:
    use axum::{
        extract::Path,
        response::{IntoResponse, Response},
        routing::get,
        Router,
    };
    use axum_extra::extract::CookieJar;
    use http::{header::SET_COOKIE, HeaderMap, HeaderValue, StatusCode};
    use std::net::SocketAddr;
    use time::Duration;
     
    async fn set_cookie(Path(path_param): Path<String>) -> impl IntoResponse {
        let mut headers = HeaderMap::new();
        let cookie_value_id = "some_id_value";
        let cookie_value_token = "some_token_value";
        let cookie_expiry = Duration::hours(1);
     
        // 设置id的Cookie
        let cookie_id = format!(
            "id={}; Expires={}; Path=/",
            cookie_value_id,
            (time::OffsetDateTime::now_utc() + cookie_expiry).to_rfc1123()
        );
        headers.insert(
            SET_COOKIE,
            HeaderValue::from_str(&cookie_id).unwrap(),
        );
     
        // 设置token的Cookie
        let cookie_token = format!(
            "token={}; Expires={}; Path=/",
            cookie_value_token,
            (time::OffsetDateTime::now_utc() + cookie_expiry).to_rfc1123()
        );
        headers.insert(
            SET_COOKIE,
            HeaderValue::from_str(&cookie_token).unwrap(),
        );
     
        let response = Response::builder()
           .status(StatusCode::OK)
           .headers(headers)
           .body(format!("Set cookies for path parameter: {}", path_param).into())
           .unwrap();
        response
    }
     
    #[tokio::main]
    async fn main() {
        let app = Router::new()
           .route("/set - cookie/{path_param}", get(set_cookie));
     
        let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
        axum::Server::bind(&addr)
           .serve(app.into_make_service())
           .await
           .unwrap();
    }
    • 在这个示例中:
      • 首先创建了一个HeaderMap来存储HTTP头信息。
      • 定义了Cookie的值(cookie_value_idcookie_value_token)以及过期时间(cookie_expiry)。
      • 对于idtokenCookie,分别构造了符合格式的Cookie字符串,包括值、过期时间和路径(Path=/表示这个Cookie适用于整个域名下的所有路径)。
      • 将构造好的Cookie字符串插入到HeaderMap中的SET - COOKIE头中。
      • 最后构建一个包含SET - COOKIE头的响应,发送给客户端。
  2. 注意事项
    • 安全性:在设置Cookie时,要注意安全问题。例如,对于敏感信息(如用户认证的token),应该考虑使用安全的传输协议(如https),并且可以设置HttpOnlySecure属性来增强安全性。
    • 有效期:合理设置Cookie的有效期,避免过长或过短的有效期带来的安全风险或用户体验问题。