mercredi 19 octobre 2016

Best Design for HTTP Headers Container C++

I'm writing an HTTP client in C++11/14 (VS 2015) for practice with asynchronous and network programming using ASIO (standalone, not boost, by the way, so please refrain from boost-specific solutions). This is a fairly basic question, but I nonetheless would appreciate an answer.

struct Header {
    Header(const std::string& key, const std::string& val); // initializes key/val
    std::string key, val;
    bool operator==(const Header& header); // returns true if key/val are equal
    friend std::ostream& operator<<(std::ostream& os, const Header& header) {
        os << header.key << ": " << header.val;
        return os;
    }
};

I've run into an issue, though. Some HTTP headers can be repeated. Others should not be. In particular, when I generate the "Host: website.com" header, I want to check and see if the user has not already input a Host parameter.

  • My initial thought was to use std::unordered_set<Header> and provide a hash function that only hashes the Key value, thus preventing duplicates. However, some headers are perfectly valid to duplicate. Set-Cookie for example
  • I then thought of creating a vector similar to this:

    static const std::unordered_set<std::string, HashIgnoreCase>& AllowedDuplicates{
        "set-cookie",
        "cookie",
    }; // HashIgnoreCase uses std::hash<std::string> on lowercase-converted strings.
    
    

    Then use that to check user-provided values. However, this seemed ugly since I'd have on std::unordered_set<Header> for most headers and a std::vector<Header> for the duplicate headers.

  • Another idea would be to completely restrict the user from providing headers that should be singular, such as throwing an exception (or some clever static_assert) to prevent values like "Host" and "Content-Length" from being provided by the user, but that seems functionally restrictive, which is not typically my goal.

What would be the best way to go about this?

Aucun commentaire:

Enregistrer un commentaire