From 5b6002ffa927ae9987d978126fa7cc30067ac1f2 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 22 Jul 2015 11:46:42 +0200 Subject: [PATCH 1/1] Split HTTP header parsing into a common function. --- httpinput.cpp | 31 +++++++------------------------ parse.cpp | 27 +++++++++++++++++++++++++++ parse.h | 6 ++++++ 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/httpinput.cpp b/httpinput.cpp index 043c07c..025fd45 100644 --- a/httpinput.cpp +++ b/httpinput.cpp @@ -222,31 +222,14 @@ bool HTTPInput::parse_response(const std::string &request) return false; } - multimap parameters; - for (size_t i = 1; i < lines.size(); ++i) { - size_t split = lines[i].find(":"); - if (split == string::npos) { - log(WARNING, "[%s] Ignoring malformed HTTP response line '%s'", - url.c_str(), lines[i].c_str()); - continue; - } - - string key(lines[i].begin(), lines[i].begin() + split); - - // Skip any spaces after the colon. - do { - ++split; - } while (split < lines[i].size() && lines[i][split] == ' '); + multimap parameters = extract_headers(lines, url); - string value(lines[i].begin() + split, lines[i].end()); - - // Remove “Content-encoding: metacube”. - // TODO: Make case-insensitive. - if (key == "Content-encoding" && value == "metacube") { - continue; - } - - parameters.insert(make_pair(key, value)); + // Remove “Content-encoding: metacube”. + // TODO: Make case-insensitive. + multimap::iterator encoding_it = + parameters.find("Content-encoding"); + if (encoding_it != parameters.end() && encoding_it->second == "metacube") { + parameters.erase(encoding_it); } // Change “Server: foo” to “Server: metacube/0.1 (reflecting: foo)” diff --git a/parse.cpp b/parse.cpp index c14b47f..c33543f 100644 --- a/parse.cpp +++ b/parse.cpp @@ -3,6 +3,7 @@ #include #include +#include "log.h" #include "parse.h" using namespace std; @@ -55,6 +56,32 @@ vector split_lines(const string &str) return ret; } +multimap extract_headers(const vector &lines, const string &log_context) +{ + multimap parameters; + for (size_t i = 1; i < lines.size(); ++i) { + size_t split = lines[i].find(":"); + if (split == string::npos) { + log(WARNING, "[%s] Ignoring malformed HTTP response line '%s'", + log_context.c_str(), lines[i].c_str()); + continue; + } + + string key(lines[i].begin(), lines[i].begin() + split); + + // Skip any spaces after the colon. + do { + ++split; + } while (split < lines[i].size() && lines[i][split] == ' '); + + string value(lines[i].begin() + split, lines[i].end()); + + parameters.insert(make_pair(key, value)); + } + + return parameters; +} + #define MAX_REQUEST_SIZE 16384 /* 16 kB. */ RequestParseStatus wait_for_double_newline(string *existing_data, const char *new_data, size_t new_data_size) diff --git a/parse.h b/parse.h index de26064..a56b1f4 100644 --- a/parse.h +++ b/parse.h @@ -4,6 +4,7 @@ // Various routines that deal with parsing; both HTTP requests and more generic text. #include +#include #include #include @@ -13,6 +14,11 @@ std::vector split_tokens(const std::string &line); // Split a string on \n or \r\n, e.g. "foo\nbar\r\n\nbaz\r\n\r\n" -> {"foo", "bar", "baz"}. std::vector split_lines(const std::string &str); +// Extract HTTP headers from a request or response. Ignores the first line, +// where the verb or the return code is. +std::multimap extract_headers( + const std::vector &lines, const std::string &log_context); + // Add the new data to an existing string, looking for \r\n\r\n // (typical of HTTP requests and/or responses). Will return one // of the given statuses. -- 2.39.5