Add a QueryParameters class.

This wraps libevent's evhttp_parse_query_str and friends. It's easier to use
than the raw libevent stuff because it handles initialization (formerly not
done properly in profiler.cc) and cleans up with RAII.
This commit is contained in:
Scott Lamb 2016-01-16 18:00:58 -08:00
parent b18f6ba237
commit 055883d248
3 changed files with 28 additions and 6 deletions

View File

@ -36,7 +36,6 @@
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <sys/types.h>

View File

@ -36,6 +36,7 @@
#include <dirent.h>
#include <stdarg.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <sys/types.h>
@ -45,6 +46,7 @@
#include <string>
#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
#include <event2/http.h>
#include <glog/logging.h>
#include <re2/stringpiece.h>
@ -53,6 +55,30 @@
namespace moonfire_nvr {
// Single-use object to represent a set of HTTP query parameters.
class QueryParameters {
public:
// Parse parameters from the given URI.
// Caller should check ok() afterward.
QueryParameters(const char *uri) {
TAILQ_INIT(&me_);
ok_ = evhttp_parse_query_str(uri, &me_) == 0;
}
QueryParameters(const QueryParameters &) = delete;
void operator=(const QueryParameters &) = delete;
~QueryParameters() { evhttp_clear_headers(&me_); }
bool ok() const { return ok_; }
const char *Get(const char *param) const {
return evhttp_find_header(&me_, param);
}
private:
struct evkeyvalq me_;
bool ok_ = false;
};
// Wrapped version of libevent's "struct evbuffer" which uses RAII and simply
// aborts the process if allocations fail. (Moonfire NVR is intended to run on
// Linux systems with the default vm.overcommit_memory=0, so there's probably

View File

@ -45,7 +45,6 @@
#include <event2/buffer.h>
#include <event2/event.h>
#include <event2/keyvalq_struct.h>
#include <event2/http.h>
#include <gperftools/profiler.h>
#include <glog/logging.h>
@ -112,12 +111,10 @@ void StartProfileCallback(struct evhttp_request *req, void *arg) {
"Profiling already in progress");
}
struct timeval timeout = {0, 0};
struct evkeyvalq query_options;
evhttp_parse_query(evhttp_request_get_uri(req), &query_options);
const char *seconds_value = evhttp_find_header(&query_options, "seconds");
QueryParameters params(evhttp_request_get_uri(req));
const char *seconds_value = params.Get("seconds");
timeout.tv_sec =
seconds_value == nullptr ? kDefaultProfileSeconds : atoi(seconds_value);
evhttp_clear_headers(&query_options);
if (timeout.tv_sec <= 0) {
return evhttp_send_error(req, HTTP_BADREQUEST, "invalid seconds");
}