I'd like to write a function that returns impl Reply
, i.e. a Warp handler. This function does some business logic and then should return two Set-Cookie
headers; the contents of each cookie is different and dependent on the business logic. I had been using a pattern like this:
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",
))
}
However this will result in only the second cookie being set. Separately there's warp::filters::reply::headers
, which initially seemed to be what I want but it's unclear how this can play nice with reply
above.
I was able to work around this by converting the reply
into a Response
and then manually manipulating the response. This is similar to cperez08's answer, but allows for two headers of the same name to be attached to the response:
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)
}