Beast: Specify different 'Fields' container allowing multiple identically named headers?

Created on 14 Jul 2018  Â·  8Comments  Â·  Source: boostorg/beast

Version of Beast

Beast 167

Steps necessary to reproduce the problem

http::responsehttp::string_body res{ };
res.set("Set-Cookie", "theme = dark;");
res.set("Set-Cookie", "token = abc123;");

All relevant compiler information

No compiler errors.

The problem with my code above is that the default 'Fields' container will only permit you to add unique header names. This is a problem when trying to set more than one cookie since each distinct cookie requires its very own 'Set-Cookie' header.

Example desired response output:

HTTP/1.0 200 OK
Set-Cookie: theme = dark;
Set-Cookie: token = abc123;
…

Is there an example of how to override the default 'Fields' container with one that will allow multiple identical header names? Thank you!

All 8 comments

I am certain that basic_fields allows the same field to appear more than once, as these tests indicate:
https://github.com/boostorg/beast/blob/e9e5d159c6f93a6901d8a2e310e6cd1703e38744/test/beast/http/fields.cpp#L369

Also the documentation says as much:
_"If one or more fields with the same name already exist, the new field will be inserted after the last field with the matching name, in serialization order."_
https://www.boost.org/doc/libs/1_67_0/libs/beast/doc/html/beast/ref/boost__beast__http__basic_fields/insert/overload2.html

What does your code look like?

Oops... I see what happened. You are using basic_fields::set, which has this behavior:
_"Set a field value, removing any other instances of that field."_

Try using basic_fields::insert instead!

Thank you Vinnie! What a wonderful library!

By the way, I think you can instead write:

http::response<http::string_body> res{ };
res.set(http::field::set_cookie, "theme = dark;");
res.set(http::field::set_cookie, "token = abc123;");

Hi ,@vinniefalco

Brothers wondered how set multiple same name header. Could you tell me how to parse the same header ?
    std::stringstream set_cookieSS;
    set_cookieSS << res[http::field::set_cookie];

My code just parsed the first 'set-cookie' how to get second or third header name "set-cookie"?

@vinniefalco Thank you,Vinnie

By the way, I think you can instead write:

http::response<http::string_body> res{ };
res.set(http::field::set_cookie, "theme = dark;");
res.set(http::field::set_cookie, "token = abc123;");

Documentation of set mentions

... removing any other instances of that field

So In the example you provided the value theme = dark will be replaced by token = abc123. Is that right ? or there is something special about Set-Cookie header ?

The Set-Cookie field is required to have multiple instances in the response header. Hence either the http framework or beast should have an exception for this specific field. So for all? other fields set will be used but for http::field::set_cookie it will go through insert instead.

I have a function to patch a boost::beast::http::response and add the headers from a member variable. This is how it looks.

template<class Body, class Fields>
void patch(boost::beast::http::message<false, Body, Fields>& res){
    for(const auto& header: _response_headers){
        if(header.name() != boost::beast::http::field::set_cookie){
            res.set(header.name(), header.value());
        }
    }
    res.erase(boost::beast::http::field::set_cookie);
    for(const auto& header: _response_headers){
        if(header.name() == boost::beast::http::field::set_cookie){
            res.insert(header.name(), header.value());
        }
    }
}

I was wondering whether this implementation is okay or it is doing something that beast already does ? Is there any other header that is required to have multiple instances ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xemwebe picture xemwebe  Â·  6Comments

MarcoRhayden picture MarcoRhayden  Â·  6Comments

chrgrd picture chrgrd  Â·  4Comments

inetic picture inetic  Â·  4Comments

nguoithichkhampha picture nguoithichkhampha  Â·  7Comments