如何将同名的两个 headers 附加到 Warp `Reply`?

How can two headers of the same name be attached to a Warp `Reply`?

我想编写一个 returns impl Reply 的函数,即 Warp 处理程序。这个函数做一些业务逻辑然后应该 return 两个 Set-Cookie headers;每个 cookie 的内容都不同,并且取决于业务逻辑。我一直在使用这样的模式:

async fn my_handler() -> anyhow::Result<impl Reply> {
    // Some business logic...

    let reply = warp::reply::json(&json!({}));
    let reply = warp::reply::with_status(reply, StatusCode::OK);
    let reply = warp::reply::with_header(
        reply,
        header::SET_COOKIE,
        "foo=bar",
    );

    Ok(warp::reply::with_header(
        reply,
        header::SET_COOKIE,
        "baz=qux",
    ))
}

然而,这将导致仅设置第二个 cookie。另外还有 warp::filters::reply::headers,最初似乎是我想要的,但不清楚它如何与上面的 reply 配合使用。

如果您想更轻松地添加多个 header,您可以使用响应构建器附加多个 header。

let builder = warp::http::response::Builder::new();

return builder
.header("content-type", "application/json")
.header("my-header-1", "my-val-1")
.header("my-header-2", "my-val-2")
.status(200)
.body(json!(&struct_rs).to_string())
.unwrap()

builder.unwrap 已经实施 warp::Reply.

但是您面对的是不同的,因为 header 具有相同的名称,这就是被覆盖的原因,您需要在设置 cookie header.

之前附加值

我能够通过将 reply 转换为 Response 然后手动操作响应来解决这个问题。这类似于 cperez08 的回答,但允许将 同名 中的两个 headers 附加到响应中:

async fn my_handler() -> anyhow::Result<impl Reply> {
    // Some business logic...

    let reply = warp::reply::json(&json!({}));
    let reply = warp::reply::with_status(reply, StatusCode::OK);

    // Set multiple e.g. cookies.
    let mut cookies = HeaderMap::new();
    cookies.append(header::SET_COOKIE, HeaderValue::from_str("foo").unwrap());
    cookies.append(header::SET_COOKIE, HeaderValue::from_str("bar").unwrap());

    // Convert `reply` into a `Response` so we can extend headers.
    let mut response = reply.into_response();
    let headers = response.headers_mut();
    headers.extend(cookies);

    Ok(response)
}