MXS-1220: Add option parsing

The options of a request are now parsed and exposed by the HttpRequest
class.

Added tests for the request options.

Also added missing error handling of invalid requests.
This commit is contained in:
Markus Mäkelä
2017-04-17 04:04:59 +03:00
committed by Markus Mäkelä
parent 9d0d394361
commit 34ee4a1997
3 changed files with 167 additions and 24 deletions

View File

@ -14,6 +14,7 @@
#include "maxscale/httprequest.hh"
#include <ctype.h>
#include <string.h>
/** TODO: Move this to a C++ string utility header */
namespace maxscale
@ -52,17 +53,68 @@ static inline string& trim(string& str)
HttpRequest* HttpRequest::parse(string data)
{
size_t pos = data.find("\r\n");
if (pos == string::npos)
{
return NULL;
}
string request_line = data.substr(0, pos);
data.erase(0, pos + 2);
pos = request_line.find(" ");
/** Request method */
if ((pos = request_line.find(" ")) == string::npos)
{
return NULL;
}
string verb = request_line.substr(0, pos);
request_line.erase(0, pos + 1);
pos = request_line.find(" ");
/** Get the combined URL/option string */
if ((pos = request_line.find(" ")) == string::npos)
{
return NULL;
}
string uri = request_line.substr(0, pos);
request_line.erase(0, pos + 1);
/** Process request options */
pos = uri.find("?");
map<string, string> options;
if (pos != string::npos)
{
string optionstr = uri.substr(pos + 1);
uri.erase(pos);
char buf[optionstr.size() + 1];
strcpy(buf, optionstr.c_str());
char* saved;
char* tok = strtok_r(buf, ",", &saved);
while (tok && *tok)
{
string opt(tok);
pos = opt.find("=");
if (pos != string::npos)
{
string key = opt.substr(0, pos - 1);
string value = opt.substr(pos + 1);
options[key] = value;
}
else
{
/** Invalid option */
return NULL;
}
tok = strtok_r(NULL, ",", &saved);
}
}
pos = request_line.find("\r\n");
string http_version = request_line.substr(0, pos);
request_line.erase(0, pos + 2);
@ -86,10 +138,18 @@ HttpRequest* HttpRequest::parse(string data)
header_line.erase(0, pos + 1);
headers[key] = mxs::trim(header_line);
}
else
{
/** Invalid header */
return NULL;
}
}
/** The headers are now processed and consumed. The message body is
* the only thing left in the request string. */
/**
* The headers are now processed and consumed. The message body is
* the only thing left in the request string and it should be a JSON object.
* Attempt to parse it and return an error if it fails.
*/
bool ok = false;
HttpRequest* request = NULL;
@ -120,11 +180,12 @@ HttpRequest* HttpRequest::parse(string data)
if (ok)
{
request = new HttpRequest();
request->m_verb = verb_value;
request->m_resource = uri;
request->m_headers = headers;
request->m_options = options;
request->m_json.reset(body);
request->m_json_string = data;
request->m_resource = uri;
request->m_verb = verb_value;
}
return request;