patterncppMinor
Parsing httpline
Viewed 0 times
parsinghttplinestackoverflow
Problem
I have an HTTP server class (.hpp & cpp). I am trying to improve reserve data from the socket class because I have
This is my old code:
I just need a way to improve it because getting data from the socket line by line is too much calling. Also, when I pass to struct, I pass this string "Host: 169.254.80.80:8080"
"Host: 169.254.80.80:8080\r\nConnection: keep-alive\r\nAccept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8\r\nUser-Agent:
Mozilla/5.0 (Windows NT 6.3; WOW64)
AppleWebKit/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\n
Accept-Language: en-US,en;q=0.8,ar;q=0.6 ";
s.getline() to get HTTP call. My s.RecvData() gets data line by line in an infinite loop to build HTTP struct.This is my old code:
while (1) {
line = s.RecvData();
//httpline = s.Getline();
if (line.empty()) break;
//find location of tab"\t"
int location_tab_char = line.find_first_of(" ");
int loacation_End_chars = line.find_first_of("\r\n");
if (loacation_End_chars == 0)
{
break;
}
if ("Host:" == line.substr(0, location_tab_char))
{
req.hostName_ = line.substr(0, loacation_End_chars);
}
else if ("Connection:" == line.substr(0, location_tab_char))
{
req.conn_ = line.substr(0, loacation_End_chars);
}
else if ("Accept:" == line.substr(0, location_tab_char))
{
req.accept_ = line.substr(0, loacation_End_chars);
}
else if ("Accept-Language:" == line.substr(0, location_tab_char))
{
req.acceptLanguage_ = line.substr(0, loacation_End_chars);
}
else if ("Accept-Encoding:" == line.substr(0, location_tab_char))
{
req.acceptEncoding_ = line.substr(0, loacation_End_chars);
}
else if ("User-Agent:" == line.substr(0, location_tab_char))
{
req.userAgent_ = line.substr(0, loacation_End_chars);
}
}I just need a way to improve it because getting data from the socket line by line is too much calling. Also, when I pass to struct, I pass this string "Host: 169.254.80.80:8080"
"Host: 169.254.80.80:8080\r\nConnection: keep-alive\r\nAccept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8\r\nUser-Agent:
Mozilla/5.0 (Windows NT 6.3; WOW64)
AppleWebKit/537.36\r\nAccept-Encoding: gzip,deflate,sdch\r\n
Accept-Language: en-US,en;q=0.8,ar;q=0.6 ";
Solution
Your code can be made smaller and without repeated constructs, by mapping your keys to values in a map:
// #include
std::map headers;
while(true) { // better use true instead of 1
line = s.RecvData();
if (line.empty() || line == "\r\n\r\n")
break;
auto key_value_sep = line.find(":"); // do not split by space
// you could stop here in case of an exception in the data
// if(0 == key_value_sep || std::string::npos == key_value_sep)
// throw std::runtime_error{"..."}; // or break, or whatever
// line is a single line; as such, end chars location not needed
// int loacation_End_chars = line.find_first_of("\r\n");
auto key = line.substr(0, key_value_separator);
auto value = line.substr(key_value_separator + 2, // skip ": "
line.size() - key.size() - 4); // size less key,
// separator and
// "\r\n"
// you could break here in case of an exception in the data
// if (value.empty() || key.empty()) || ...)
// throw std::runtime_error{"..."}; // or break, or whatever
// set header
headers[key] += value;
}
// set headers (or use directly from map)
req.hostName_ = headers["Host"];
req.conn_ = headers["Connection"];
req.accept_ = headers["Accept"];
req.acceptLanguage_ = headers["Accept-Language"];
req.acceptEncoding_ = headers["Accept-Encoding"];
req.userAgent_ = headers["User-Agent"];Code Snippets
// #include <map>
std::map<std::string,std::string> headers;
while(true) { // better use true instead of 1
line = s.RecvData();
if (line.empty() || line == "\r\n\r\n")
break;
auto key_value_sep = line.find(":"); // do not split by space
// you could stop here in case of an exception in the data
// if(0 == key_value_sep || std::string::npos == key_value_sep)
// throw std::runtime_error{"..."}; // or break, or whatever
// line is a single line; as such, end chars location not needed
// int loacation_End_chars = line.find_first_of("\r\n");
auto key = line.substr(0, key_value_separator);
auto value = line.substr(key_value_separator + 2, // skip ": "
line.size() - key.size() - 4); // size less key,
// separator and
// "\r\n"
// you could break here in case of an exception in the data
// if (value.empty() || key.empty()) || ...)
// throw std::runtime_error{"..."}; // or break, or whatever
// set header
headers[key] += value;
}
// set headers (or use directly from map)
req.hostName_ = headers["Host"];
req.conn_ = headers["Connection"];
req.accept_ = headers["Accept"];
req.acceptLanguage_ = headers["Accept-Language"];
req.acceptEncoding_ = headers["Accept-Encoding"];
req.userAgent_ = headers["User-Agent"];Context
StackExchange Code Review Q#47416, answer score: 6
Revisions (0)
No revisions yet.