Split HTTP header parsing into a common function.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 22 Jul 2015 09:46:42 +0000 (11:46 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 22 Jul 2015 09:46:42 +0000 (11:46 +0200)
httpinput.cpp
parse.cpp
parse.h

index 043c07c..025fd45 100644 (file)
@@ -222,31 +222,14 @@ bool HTTPInput::parse_response(const std::string &request)
                return false;
        }
 
-       multimap<string, string> 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<string, string> 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<string, string>::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)”
index c14b47f..c33543f 100644 (file)
--- a/parse.cpp
+++ b/parse.cpp
@@ -3,6 +3,7 @@
 #include <string>
 #include <vector>
 
+#include "log.h"
 #include "parse.h"
 
 using namespace std;
@@ -55,6 +56,32 @@ vector<string> split_lines(const string &str)
        return ret;
 }
 
+multimap<string, string> extract_headers(const vector<string> &lines, const string &log_context)
+{
+       multimap<string, string> 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 (file)
--- a/parse.h
+++ b/parse.h
@@ -4,6 +4,7 @@
 // Various routines that deal with parsing; both HTTP requests and more generic text.
 
 #include <stddef.h>
+#include <map>
 #include <string>
 #include <vector>
 
@@ -13,6 +14,11 @@ std::vector<std::string> 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<std::string> 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<std::string, std::string> extract_headers(
+       const std::vector<std::string> &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.