8 changed files with 258 additions and 218 deletions
@ -1,56 +1,58 @@
|
||||
#ifndef _TOREST_HTTP_HPP_ |
||||
#define _TOREST_HTTP_HPP_ |
||||
#ifndef _TR_HTTP_HPP_ |
||||
#define _TR_HTTP_HPP_ |
||||
|
||||
#include <json.hpp> |
||||
#include <unordered_map> |
||||
|
||||
namespace http { |
||||
/// http codes
|
||||
enum status { |
||||
/*! Standard response for successful HTTP requests. */ ok=200, |
||||
/*! The request has been fulfilled, resulting in the creation of a new resource. */ created=201, |
||||
/*! The request has been accepted for processing, but the processing has not been completed. */ accepted=202, |
||||
/*! The server successfully processed the request and is not returning any content. */ no_content=204, |
||||
/*! The server cannot or will not process the request due to an apparent client error */ bad_request=400, |
||||
/*! Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided. */ unauthorized=401, |
||||
/*! Reserved for future use. The */ payment_required=402, |
||||
/*! the request was a valid request, but the server is refusing to respond to it. */ forbidden=403, |
||||
/*! The requested resource could not be found but may be available in the future. */ not_found=404, |
||||
/*! Allowed A request method is not supported for the requested resource */ method_not_allowed=405, |
||||
/*! The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request. */ not_acceptable=406, |
||||
/*! A generic error message, given when an unexpected condition was encountered and no more specific message is suitable. */ internal_server_error=500, |
||||
/*! The server either does not recognize the request method, or it lacks the ability to fulfill the request. */ not_implemented=501, |
||||
/*! The server was acting as a gateway or proxy and received an invalid response from the upstream server. */ bad_gateway=502, |
||||
/*! The server is currently unavailable (because it is overloaded or down for maintenance). Generally, this is a temporary state. */ service_unavailable=503, |
||||
/*! Gateway timed out */ gateway_timeout=504, |
||||
/*! http-version not supported */ http_version_not_supported=505 |
||||
}; |
||||
typedef std::pair<std::string,std::string> header; |
||||
typedef std::unordered_map<std::string,std::string> headers; |
||||
/// http codes
|
||||
enum status { |
||||
/*! Standard response for successful HTTP requests. */ ok = 200, |
||||
/*! The request has been fulfilled, resulting in the creation of a new resource. */ created = 201, |
||||
/*! The request has been accepted for processing, but the processing has not been completed. */ accepted = 202, |
||||
/*! The server successfully processed the request and is not returning any content. */ no_content = 204, |
||||
/*! The server cannot or will not process the request due to an apparent client error */ bad_request = 400, |
||||
/*! Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided. */ unauthorized = 401, |
||||
/*! Reserved for future use. The */ payment_required = 402, |
||||
/*! the request was a valid request, but the server is refusing to respond to it. */ forbidden = 403, |
||||
/*! The requested resource could not be found but may be available in the future. */ not_found = 404, |
||||
/*! Allowed A request method is not supported for the requested resource */ method_not_allowed = 405, |
||||
/*! The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request. */ not_acceptable = 406, |
||||
/*! A generic error message, given when an unexpected condition was encountered and no more specific message is suitable. */ internal_server_error = 500, |
||||
/*! The server either does not recognize the request method, or it lacks the ability to fulfill the request. */ not_implemented = 501, |
||||
/*! The server was acting as a gateway or proxy and received an invalid response from the upstream server. */ bad_gateway = 502, |
||||
/*! The server is currently unavailable (because it is overloaded or down for maintenance). Generally, this is a temporary state. */ service_unavailable = 503, |
||||
/*! Gateway timed out */ gateway_timeout = 504, |
||||
/*! http-version not supported */ http_version_not_supported = 505 |
||||
}; |
||||
typedef std::pair<std::string, std::string> header; |
||||
typedef std::unordered_map<std::string, std::string> headers; |
||||
|
||||
/// creates a http::code object out of a http::status code
|
||||
class code { |
||||
public: |
||||
/// creates a http::code object out of a http::status code
|
||||
class code { |
||||
public: |
||||
code(status status); |
||||
public: |
||||
|
||||
public: |
||||
status first; |
||||
std::string second; |
||||
}; |
||||
}; |
||||
|
||||
class response { |
||||
public: |
||||
friend std::ostream& operator<<(std::ostream& os,const response &rh){ return rh.do_response(os); } |
||||
response():status_code(http::ok){} |
||||
void set_body(const std::string &content) { body=content; } |
||||
class response { |
||||
public: |
||||
friend std::ostream &operator<<(std::ostream &os, const response &rh) { return rh.do_response(os); } |
||||
response() : status_code(http::ok) {} |
||||
void set_body(const std::string &content) { body = content; } |
||||
void set_body(const nlohmann::json &json); |
||||
void add_header(const http::header &header) { response_headers.emplace(header); } |
||||
void set_status(http::status code) { status_code=code; } |
||||
std::ostream& do_response(std::ostream &os) const; |
||||
protected: |
||||
void set_status(http::status code) { status_code = code; } |
||||
std::ostream &do_response(std::ostream &os) const; |
||||
|
||||
protected: |
||||
std::string body; |
||||
headers response_headers; |
||||
code status_code; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
#endif // _TOREST_HTTP_HPP_
|
||||
#endif |
||||
|
||||
@ -1,70 +1,75 @@
|
||||
#ifndef _TR_SESSION_HPP_ |
||||
#define _TR_SESSION_HPP_ |
||||
|
||||
#include <http.hpp> |
||||
#include <util.hpp> |
||||
|
||||
namespace tr{ |
||||
namespace session { |
||||
template<class torrent_session, class request, class response> |
||||
void get(torrent_session&session,response resp,request req){ |
||||
namespace tr { |
||||
namespace session { |
||||
template <class torrent_session, class request, class response> |
||||
void get(torrent_session &session, response resp, request req) { |
||||
auto http_response = http::response(); |
||||
if (session.is_valid()) { |
||||
const auto settings = session.get_settings(); |
||||
http_response.set_body({ |
||||
{ "paused", session.is_paused() }, |
||||
{ "port", session.listen_port() }, |
||||
{ "dht_enabled", session.is_dht_running() }, |
||||
{ "down_limit", settings.get_int(settings.download_rate_limit) }, |
||||
{ "up_limit", settings.get_int(settings.upload_rate_limit) }, |
||||
{ "torrents", session.get_torrents().size() }, //TODO Optimize
|
||||
// { "default_download_dir", default_download_dir.filename().string() },
|
||||
// { "root_dir", root_dir.string() },
|
||||
{"paused", session.is_paused()}, |
||||
{"port", session.listen_port()}, |
||||
{"dht_enabled", session.is_dht_running()}, |
||||
{"down_limit", settings.get_int(settings.download_rate_limit)}, |
||||
{"up_limit", settings.get_int(settings.upload_rate_limit)}, |
||||
{"torrents", session.get_torrents().size()}, //TODO Optimize
|
||||
// { "default_download_dir", default_download_dir.filename().string() },
|
||||
// { "root_dir", root_dir.string() },
|
||||
}); |
||||
} else { |
||||
auto response_code = http::code(http::service_unavailable); |
||||
http_response.set_body({{"code", response_code.first}, { "status", response_code.second}}); |
||||
http_response.set_body({{"code", response_code.first}, {"status", response_code.second}}); |
||||
http_response.set_status(response_code.first); |
||||
} |
||||
*resp << http_response; |
||||
} |
||||
template<class torrent_session, class request, class response> |
||||
void patch(torrent_session&session,response resp,request req){ |
||||
} |
||||
template <class torrent_session, class request, class response> |
||||
void patch(torrent_session &session, response resp, request req) { |
||||
auto http_response = http::response(); |
||||
if (!session.is_valid()) { |
||||
auto response_code = http::code(http::service_unavailable); |
||||
http_response.set_body({{"code",response_code.first},{"status", response_code.second}}); |
||||
http_response.set_body({{"code", response_code.first}, {"status", response_code.second}}); |
||||
http_response.set_status(response_code.first); |
||||
} else { |
||||
const auto json=util::json::parse(req->content); |
||||
if(json.is_object() && !json.is_null()) { |
||||
if(util::json::get("paused",json,session.is_paused())) |
||||
const auto json = util::json::parse(req->content); |
||||
if (json.is_object() && !json.is_null()) { |
||||
if (util::json::get("paused", json, session.is_paused())) |
||||
session.pause(); |
||||
else |
||||
session.resume(); |
||||
auto settings = session.get_settings(); |
||||
const auto new_listen_port=util::json::get("port",json,session.listen_port()); |
||||
if(new_listen_port!=session.listen_port()) |
||||
settings.set_str(settings.listen_interfaces,"0.0.0.0:"+std::to_string(new_listen_port));
|
||||
const auto new_dht_enabled=util::json::get("dht_enabled",json,session.is_dht_running()); |
||||
if(new_dht_enabled!=session.is_dht_running()) |
||||
settings.set_bool(settings.enable_dht,new_dht_enabled); |
||||
auto old_limit=settings.get_int(settings.download_rate_limit); |
||||
auto new_limit=util::json::get("down_limit",json,old_limit); |
||||
if(new_limit!=old_limit) |
||||
settings.set_int(settings.download_rate_limit,new_limit); |
||||
old_limit=settings.get_int(settings.upload_rate_limit); |
||||
new_limit=util::json::get("up_limit",json,old_limit); |
||||
if(new_limit!=old_limit) |
||||
settings.set_int(settings.upload_rate_limit,new_limit); |
||||
const auto new_listen_port = util::json::get("port", json, session.listen_port()); |
||||
if (new_listen_port != session.listen_port()) |
||||
settings.set_str(settings.listen_interfaces, "0.0.0.0:" + std::to_string(new_listen_port)); |
||||
const auto new_dht_enabled = util::json::get("dht_enabled", json, session.is_dht_running()); |
||||
if (new_dht_enabled != session.is_dht_running()) |
||||
settings.set_bool(settings.enable_dht, new_dht_enabled); |
||||
auto old_limit = settings.get_int(settings.download_rate_limit); |
||||
auto new_limit = util::json::get("down_limit", json, old_limit); |
||||
if (new_limit != old_limit) |
||||
settings.set_int(settings.download_rate_limit, new_limit); |
||||
old_limit = settings.get_int(settings.upload_rate_limit); |
||||
new_limit = util::json::get("up_limit", json, old_limit); |
||||
if (new_limit != old_limit) |
||||
settings.set_int(settings.upload_rate_limit, new_limit); |
||||
session.apply_settings(settings); |
||||
auto response_code = http::code(http::accepted); |
||||
http_response.set_body({{"code",response_code.first},{"status", response_code.second}}); |
||||
http_response.set_body({{"code", response_code.first}, {"status", response_code.second}}); |
||||
http_response.set_status(response_code.first); |
||||
} else { |
||||
auto response_code = http::code(http::bad_request); |
||||
http_response.set_body({{"code",response_code.first},{"status", response_code.second}}); |
||||
http_response.set_body({{"code", response_code.first}, {"status", response_code.second}}); |
||||
http_response.set_status(response_code.first); |
||||
} |
||||
} |
||||
*resp << http_response; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#endif |
||||
@ -1,84 +1,82 @@
|
||||
#ifndef _BT_HELPERS_HPP_ |
||||
#define _BT_HELPERS_HPP_ |
||||
#ifndef _TR_UTIL_HPP_ |
||||
#define _TR_UTIL_HPP_ |
||||
|
||||
#include <unordered_map> |
||||
#include <boost/regex.hpp> |
||||
#include <json.hpp> |
||||
#include <unordered_map> |
||||
|
||||
namespace util { |
||||
class uri { |
||||
public: |
||||
auto static parse(const std::string &request_path){ |
||||
std::unordered_map<std::string,std::string> options; |
||||
class uri { |
||||
public: |
||||
auto static parse(const std::string &request_path) { |
||||
std::unordered_map<std::string, std::string> options; |
||||
std::string option, value; |
||||
bool collect=false; |
||||
for(auto &c:request_path){ |
||||
switch(c){ |
||||
bool collect = false; |
||||
for (auto &c : request_path) { |
||||
switch (c) { |
||||
case '&': |
||||
options.insert(std::make_pair(option,value)); |
||||
option=""; |
||||
collect=true; |
||||
options.insert(std::make_pair(option, value)); |
||||
option = ""; |
||||
collect = true; |
||||
break; |
||||
case '?': |
||||
collect=true; |
||||
collect = true; |
||||
break; |
||||
case '=': |
||||
collect=false; |
||||
value=""; |
||||
collect = false; |
||||
value = ""; |
||||
break; |
||||
default: |
||||
if(collect) |
||||
option+=c; |
||||
if (collect) |
||||
option += c; |
||||
else |
||||
value+=c; |
||||
value += c; |
||||
break; |
||||
} |
||||
} |
||||
if(!option.empty() || !value.empty()) |
||||
options.insert(std::make_pair(option,value)); |
||||
if (!option.empty() || !value.empty()) |
||||
options.insert(std::make_pair(option, value)); |
||||
return options; |
||||
} |
||||
}; |
||||
const boost::regex regex("@(https?|ftp)://(-\\.)?([^\\s/?\\.#-]+\\.?)+(/[^\\s]*)?$@", boost::regex_constants::perl | boost::regex_constants::icase); |
||||
}; |
||||
const boost::regex regex("@(https?|ftp)://(-\\.)?([^\\s/?\\.#-]+\\.?)+(/[^\\s]*)?$@", boost::regex_constants::perl | boost::regex_constants::icase); |
||||
|
||||
class json { |
||||
public: |
||||
class json { |
||||
public: |
||||
/*! @brief Wrapper for nlohmann::json::parse. If the parse fails, result.is_null() will be */ |
||||
static nlohmann::json parse(std::istream &istream) { |
||||
try { |
||||
return nlohmann::json::parse(istream); |
||||
} catch(const std::invalid_argument &exp) { |
||||
|
||||
} catch (const std::invalid_argument &exp) { |
||||
} |
||||
return nlohmann::json(nullptr); |
||||
} |
||||
/*! @brief wrapper around nlohmann::json::parse, but object returns null on throw */ |
||||
static nlohmann::json parse(const std::string &string){ |
||||
static nlohmann::json parse(const std::string &string) { |
||||
try { |
||||
return nlohmann::json::parse(string); |
||||
} catch(const std::invalid_argument &exp) { |
||||
|
||||
} catch (const std::invalid_argument &exp) { |
||||
} |
||||
return nlohmann::json(nullptr); |
||||
} |
||||
static bool has_property(const std::string &key, const nlohmann::json &object){ |
||||
auto it=object.find(key); |
||||
return it!=object.end(); |
||||
static bool has_property(const std::string &key, const nlohmann::json &object) { |
||||
auto it = object.find(key); |
||||
return it != object.end(); |
||||
} |
||||
template<class T> |
||||
static auto get(const std::string &key, const nlohmann::json &object, const T &default_value){ |
||||
if(has_property(key,object)){ |
||||
template <class T> |
||||
static auto get(const std::string &key, const nlohmann::json &object, const T &default_value) { |
||||
if (has_property(key, object)) { |
||||
T r; |
||||
try{ |
||||
r=object[key]; //TODO fix use json parser where a non-throwable exist
|
||||
} catch(const std::exception&){ |
||||
try { |
||||
r = object[key]; //TODO fix use json parser where a non-throwable exist
|
||||
} catch (const std::exception &) { |
||||
return default_value; |
||||
} |
||||
return r; |
||||
} |
||||
return default_value; |
||||
} |
||||
}; |
||||
}; |
||||
} |
||||
|
||||
#endif // _BT_HELPERS_HPP_
|
||||
#endif |
||||
|
||||
Loading…
Reference in new issue