Skip to content

headers field should be case insensitive #157

Open
@KaiPetzke

Description

@KaiPetzke

Expected behaviour

The following code snippet:

    RestClient::Connection* conn = new RestClient::Connection("https://httpbin.org");
    RestClient::Response& r = conn->get("/get");
    for(auto& name : { "date", "Date" }) {
        try {
            std::string& value = r.headers.at(name);
            std::cout << name << ": \"" << value << "\"" << std::endl;
        } catch(std::out_of_range& oor) {
            std::cout << name << ": not found" << std::endl;
        }
    }

should yield a result similiar to the following:

date: "Tue, 11 Aug 2020 19:52:17 GMT"
Date: "Tue, 11 Aug 2020 19:52:17 GMT"

Actual behaviour

The result is as follows:

date: not found
Date: "Tue, 11 Aug 2020 19:52:17 GMT"

This is an error, as according to RFC 2616: "Field names are case-insensitive". And yes, unfortunately, there are servers, that change the case of their response header fields at will.

Environment and debugging details

This happens with any C compiler and libcurl

Suggested fix:

Use a custom compare function to make the std::map in RestClient::HeaderFields case-insensitive. I have attached a file with the suggested change. Yes, it uses std::tolower(), which unfortunately is locale dependant, for conversion to lowercase. So depending on language settings, tolower() might convert, say, Ç to ç or not. If that is considered an issue, an alternative would be to explicitely only map characters in the range 'A' to 'Z' to 'a' to 'z', and use this mapping function instead of std::tolower():

    unsigned char ascii_tolower(const unsigned char c) {
        return (c >= 'A' && c <= 'Z') ? ((c - 'A') + 'a') : c;
    }

restclient.diff.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions