2

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.

kmdreko
  • 42,554
  • 6
  • 57
  • 106
maxcountryman
  • 1,562
  • 1
  • 24
  • 51

2 Answers2

3

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)
}
maxcountryman
  • 1,562
  • 1
  • 24
  • 51
1

if you want to add multiple headers easier you can use the response builder to append multiple headers.

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 already implements warp::Reply.

However what you facing is different , as the header has the same name that's why is being overrided, you need to append the values before setting the cookie header.

cperez08
  • 709
  • 4
  • 9