The trait you're referring to applies to the headers in a client-side request, for the client-side implementation in cpp-netlib. There was some work being done (incomplete) to make getting a header from the request in the server be the same as for getting the request from client request/response objects.
The reason the headers on the server side are a vector of pairs is for "efficiency" in terms of space and time. If you can pay the cost of creating a multimap on the server's handler, you should probably do that instead. The usual pattern for efficiently working through headers in a request in an efficient manner is to always do a linear scan of the headers you're looking for, and processing them as they come in. Something similar to this:
string content_type, content_length;
for (const auto& header : request.headers) {
if (header.name == "Content-Type") content_type = header.value;
if (header.name == "Content-Length") content_length = header.value;
if (!content_type.empty() && !content_length.empty()) break;
}
You may generalise this using some sort of pattern (a std::map<string, std::function<void(const std::string&)>>
perhaps) if your application requires this level of header processing.
In general though, iterating through a list of vectors shouldn't take too much time. If the number of headers is large (O(10,000)) then you have other problems. The tradeoff here is between memory locality (a vector has contiguous elements as opposed to a map that has elements typically randomly allocated in different parts of memory) and efficient lookup (logarithmic time only really makes sense after a certain size).
I completely accept the point that the convenience suffers a bit. Maybe a different data structure would be helpful here (a boost::flat_map
perhaps). But an interface improvement would be to make the code that works with client request/response also work with server request/response objects.