Commit 837091a9 authored by Micha Mueller's avatar Micha Mueller
Browse files

Refactor request handling

parent 038467a8
......@@ -11,185 +11,165 @@
#include <memory>
#include <functional>
#include <boost/algorithm/string/split.hpp>
HttpsServer::requestHandler::requestHandler(HttpsServer& httpsServer) : _httpsServer(httpsServer) {}
void HttpsServer::requestHandler::operator()(server::request const &request, server::connection_ptr connection) {
//first log some info about client
server::string_type ip = source(request);
unsigned int port = request.source_port;
server::string_type method = request.method;
std::ostringstream data;
connection->set_status(server::connection::internal_server_error);
LOG(info) << "HttpsServer: " << ip << ":" << port << " connected";
boost::network::uri::uri uri("https://" + request.destination);
server::string_type path = uri.path();
server::string_type query = uri.query();
connection->set_status(server::connection::internal_server_error);
std::ostringstream data;
server::string_type method = request.method;
//select code depending on request
if (method == "GET") {
LOG(info) << "HttpsServer: GET request of " << request.destination << " was made";
//first check if request is supported at all
if (method != "GET" && method != "PUT") {
LOG(info) << "HttpsServer: Unsupported " << method << " request was made";
connection->set_status(server::connection::not_supported);
} else {
LOG(info) << "HttpsServer: " << method << " request of " << request.destination << " was made";
std::string response = "";
std::string plugin = path;
std::string sensor = "";
std::string action = "";
std::string auth_key = query;
std::string auth_value = "";
boost::network::uri::uri uri("https://" + request.destination);
server::string_type path = uri.path();
server::string_type query = uri.query();
//do some string processing
//split up query into key and value
size_t pos = auth_key.find("=");
if (pos != std::string::npos) {
auth_value = auth_key.substr(pos+1);
auth_key.erase(pos);
}
//split up path into plugin, sensor and action
if (plugin.size() >= 2) {
if (plugin[0] == '/') {
plugin.erase(0,1);
std::vector<std::string> pathStrs;
std::vector<std::pair<std::string, std::string>> queries;
//split path into its hierarchical parts
if (path.size() >= 2) {
if (path[0] == '/') {
path.erase(0,1);
}
if (plugin[plugin.size() -1] == '/') {
plugin.erase(plugin.size() -1);
if (path[path.size() -1] == '/') {
path.erase(path.size() -1);
}
pos = plugin.find("/");
if (pos != std::string::npos) {
sensor = plugin.substr(pos+1);
plugin.erase(pos);
}
boost::split(pathStrs, path, boost::is_any_of("/"), boost::token_compress_off);
}
pos = sensor.find("/");
//split query part into the individual queries
std::vector<std::string> queryStrs;
boost::split(queryStrs, query, boost::is_any_of(";"), boost::token_compress_on);
for(auto& key : queryStrs) {
size_t pos = key.find("=");
if (pos != std::string::npos) {
action = sensor.substr(pos+1);
sensor.erase(pos);
std::string value;
value = key.substr(pos+1);
key.erase(pos);
queries.push_back(std::make_pair(key, value));
}
}
//finished string processing
//process actual request
//check if query and action are valid values
if (auth_key == "authkey" && (action == "avg")) {
//check if authkey is valid
if (_httpsServer.check_authkey(auth_value, permission::GETReq)) {
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
for(auto& p : _httpsServer._plugins) {
if (p.id == plugin) {
response = "Sensor not found!";
for(auto s : p.configurator->getSensors()) {
if (s->getName() == sensor) {
uint64_t avg = 0;
const reading_t * const cache = s->getCache();
unsigned size = s->getCacheSize();
for(unsigned i = 0; i < size; i++) {
avg += cache[i].value;
}
avg /= size;
response = plugin + "::" + sensor + " Average of last " + std::to_string(size) + " values is " + std::to_string(avg);
connection->set_status(server::connection::ok);
goto end;
}
}
}
}
} else {
response = "Invalid authentication key!";
connection->set_status(server::connection::unauthorized);
}
} else {
response = "GET requests should be of the form \"host:port/[plugin]/[sensor]/[action]?authkey=[token]\"\n"
"Where [plugin] names a plugin, [sensor] a sensor within this plugin, [action] is 'avg' and [token] is your authentication key";
connection->set_status(server::connection::bad_request);
}
end:
LOG(info) << "HttpsServer: Responding: " << response;
data << response << std::endl;
} else if (method == "PUT") {
LOG(info) << "HttpsServer: PUT request to " << request.destination << " was made";
std::string response = "";
std::string plugin = path;
std::string action = "";
std::string auth_key = query;
std::string auth_value = "";
//do some string processing
//split up query into key and value
size_t pos = auth_key.find("=");
if (pos != std::string::npos) {
auth_value = auth_key.substr(pos+1);
auth_key.erase(pos);
}
//split up path into plugin and action
if (plugin.size() >= 2) {
if (plugin[0] == '/') {
plugin.erase(0,1);
}
if (plugin[plugin.size() -1] == '/') {
plugin.erase(plugin.size() -1);
}
pos = plugin.find("/");
if (pos != std::string::npos) {
action = plugin.substr(pos+1);
plugin.erase(pos);
for (auto& p : queries) {
if (p.first == "authkey") {
auth_value = p.second;
break;
}
}
//finished string processing
//process actual request
//check if query and action are valid values
if (auth_key == "authkey" && ((action == "start") || (action == "stop"))) {
//check if authkey is valid
if (_httpsServer.check_authkey(auth_value, permission::PUTReq)) {
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
for(auto& p : _httpsServer._plugins) {
if (p.id == plugin) {
if (action == "start") {
for(auto s : p.configurator->getSensors()) {
s->startPolling();
if (pathStrs.size() < 2 || auth_value == "") {
LOG(error) << "Received malformed request";
connection->set_status(server::connection::bad_request);
} else {
std::string plugin = pathStrs[0];
//select code depending on request
if (method == "GET") {
//do some prior checks
if (pathStrs.size() < 3 || pathStrs[2] != "avg") {
response = "GET requests should be of the form \"host:port/[plugin]/[sensor]/[action]?authkey=[token]\"\n"
"Where [plugin] names a plugin, [sensor] a sensor within this plugin, [action] is 'avg' and [token] is your authentication key";
connection->set_status(server::connection::bad_request);
} else {
std::string sensor = pathStrs[1];
std::string action = pathStrs[2];
//process actual request
//check if query and action are valid values
//check if authkey is valid
if (_httpsServer.check_authkey(auth_value, permission::GETReq)) {
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
for(auto& p : _httpsServer._plugins) {
if (p.id == plugin) {
response = "Sensor not found!";
for(auto s : p.configurator->getSensors()) {
if (s->getName() == sensor) {
uint64_t avg = 0;
const reading_t * const cache = s->getCache();
unsigned size = s->getCacheSize();
for(unsigned i = 0; i < size; i++) {
avg += cache[i].value;
}
avg /= size;
response = plugin + "::" + sensor + " Average of last " + std::to_string(size) + " values is " + std::to_string(avg);
connection->set_status(server::connection::ok);
}
}
}
response = "Plugin " + plugin + ": Sensors started";
connection->set_status(server::connection::ok);
} else if (action == "stop") {
for(auto s : p.configurator->getSensors()) {
s->stopPolling();
}
} else {
response = "Invalid authentication key!";
connection->set_status(server::connection::unauthorized);
}
}
} else if (method == "PUT") {
std::string action = pathStrs[1];
//process actual request
//check if query and action are valid values
if ((action == "start") || (action == "stop")) {
//check if authkey is valid
if (_httpsServer.check_authkey(auth_value, permission::PUTReq)) {
response = "Plugin not found!";
connection->set_status(server::connection::not_found);
for(auto& p : _httpsServer._plugins) {
if (p.id == plugin) {
if (action == "start") {
for(auto s : p.configurator->getSensors()) {
s->startPolling();
}
response = "Plugin " + plugin + ": Sensors started";
connection->set_status(server::connection::ok);
} else if (action == "stop") {
for(auto s : p.configurator->getSensors()) {
s->stopPolling();
}
response = "Plugin " + plugin + ": Sensors stopped";
connection->set_status(server::connection::ok);
}
}
response = "Plugin " + plugin + ": Sensors stopped";
connection->set_status(server::connection::ok);
}
} else {
response = "Invalid authentication key!";
connection->set_status(server::connection::unauthorized);
}
} else {
response = "PUT requests should be of the form \"host:port/[plugin]/[action]?authkey=[token]\"\n"
"Where [plugin] names a plugin, [action] is either \"start\" or \"stop\" and [token] is your authentication key";
connection->set_status(server::connection::bad_request);
}
} else {
response = "Invalid authentication key!";
connection->set_status(server::connection::unauthorized);
}
} else {
response = "PUT requests should be of the form \"host:port/[plugin]/[action]?authkey=[token]\"\n"
"Where [plugin] names a plugin, [action] is either \"start\" or \"stop\" and [token] is your authentication key";
connection->set_status(server::connection::bad_request);
LOG(info) << "HttpsServer: Responding: " << response;
data << response << std::endl;
}
LOG(info) << "HttpsServer: Responding: " << response;
data << response << std::endl;
} else {
LOG(info) << "HttpsServer: Received unsupported " << method << " request";
connection->set_status(server::connection::not_supported);
}
//send response
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment