diff options
Diffstat (limited to 'contrib/epee/include/net/http_server_handlers_map2.h')
-rw-r--r-- | contrib/epee/include/net/http_server_handlers_map2.h | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h new file mode 100644 index 000000000..7a8bdd4ad --- /dev/null +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -0,0 +1,260 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + +#pragma once +#include "serialization/keyvalue_serialization.h" +#include "storages/portable_storage_template_helper.h" +#include "http_base.h" + + +#define CHAIN_HTTP_TO_MAP2() bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ + epee::net_utils::http::http_response_info& response, \ + const epee::net_utils::connection_context_base& m_conn_context) \ +{\ + LOG_PRINT_L2("HTTP [" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ + response.m_response_code = 200; \ + response.m_response_comment = "Ok"; \ + if(!handle_http_request_map(query_info, response, m_conn_context)) \ + {response.m_response_code = 404;response.m_response_comment = "Not found";} \ + return true; \ +} + + +#define BEGIN_URI_MAP2() bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \ + epee::net_utils::http::http_response_info& response_info, \ + const epee::net_utils::connection_context_base& m_conn_context) { \ + bool handled = false; \ + if(false) return true; //just a stub to have "else if" + +#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context); + +#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format + +#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) \ + else if(query_info.m_URI == s_pattern) \ + { \ + handled = true; \ + boost::uint64_t ticks = misc_utils::get_tick_count(); \ + boost::value_initialized<command_type::request> req; \ + bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \ + CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \ + boost::uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ + boost::value_initialized<command_type::response> resp;\ + if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp))) \ + { \ + LOG_ERROR("Failed to " << #callback_f << "()"); \ + response_info.m_response_code = 500; \ + response_info.m_response_comment = "Internal Server Error"; \ + return true; \ + } \ + boost::uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ + epee::serialization::store_t_to_json(static_cast<command_type::response&>(resp), response_info.m_body); \ + boost::uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ + response_info.m_mime_tipe = "application/json"; \ + response_info.m_header_info.m_content_type = " application/json"; \ + LOG_PRINT( s_pattern << " processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ + } + +#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \ + else if(query_info.m_URI == s_pattern) \ + { \ + handled = true; \ + boost::uint64_t ticks = misc_utils::get_tick_count(); \ + boost::value_initialized<command_type::request> req; \ + bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), query_info.m_body); \ + CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ + boost::uint64_t ticks1 = misc_utils::get_tick_count(); \ + boost::value_initialized<command_type::response> resp;\ + if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp))) \ + { \ + LOG_ERROR("Failed to " << #callback_f << "()"); \ + response_info.m_response_code = 500; \ + response_info.m_response_comment = "Internal Server Error"; \ + return true; \ + } \ + boost::uint64_t ticks2 = misc_utils::get_tick_count(); \ + epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), response_info.m_body); \ + boost::uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ + response_info.m_mime_tipe = " application/octet-stream"; \ + response_info.m_header_info.m_content_type = " application/octet-stream"; \ + LOG_PRINT( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ + } + +#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);handled = true;} + +#define END_URI_MAP2() return handled;} + + + + +namespace epee +{ + namespace json_rpc + { + template<typename t_param> + struct request + { + std::string version; + std::string method; + std::string id; + t_param params; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(version) + KV_SERIALIZE(method) + KV_SERIALIZE(id) + KV_SERIALIZE(params) + END_KV_SERIALIZE_MAP() + }; + + struct error + { + int64_t code; + std::string message; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(code) + KV_SERIALIZE(message) + END_KV_SERIALIZE_MAP() + }; + + struct dummy_error + { + BEGIN_KV_SERIALIZE_MAP() + END_KV_SERIALIZE_MAP() + }; + + template<typename t_param, typename t_error> + struct response + { + t_param result; + t_error error; + std::string id; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(result) + KV_SERIALIZE(error) + KV_SERIALIZE(id) + END_KV_SERIALIZE_MAP() + }; + + typedef response<std::string, error> error_response; + } +} + + + + +#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \ + { \ + boost::uint64_t ticks = epee::misc_utils::get_tick_count(); \ + epee::serialization::portable_storage ps; \ + if(!ps.load_from_json(query_info.m_body)) \ + { \ + boost::value_initialized<epee::json_rpc::error_response> rsp; \ + static_cast<epee::json_rpc::error_response&>(rsp).error.code = -32700; \ + static_cast<epee::json_rpc::error_response&>(rsp).error.message = "Parse error"; \ + epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \ + return true; \ + } \ + std::string callback_name; \ + if(!ps.get_value("method", callback_name, nullptr)) \ + { \ + epee::json_rpc::error_response rsp; \ + rsp.error.code = -32600; \ + rsp.error.message = "Invalid Request"; \ + epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \ + return true; \ + } \ + if(false) return true; //just a stub to have "else if" + +#define MAP_JON_RPC_WE(method_name, callback_f, command_type) \ + else if(callback_name == method_name) \ +{ \ + handled = true; \ + boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \ + epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\ + req.load(ps); \ + boost::uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ + boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \ + epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(resp_); \ + resp.id = req.id; \ + epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ + fail_resp.id = req.id; \ + if(!callback_f(req.params, resp.result, fail_resp.error)) \ +{ \ + epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ + return true; \ +} \ + boost::uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ + epee::serialization::store_t_to_json(resp, response_info.m_body); \ + boost::uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ + response_info.m_mime_tipe = "application/json"; \ + response_info.m_header_info.m_content_type = " application/json"; \ + LOG_PRINT( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ + return true;\ +} + + +#define MAP_JON_RPC(method_name, callback_f, command_type) \ + else if(callback_name == method_name) \ +{ \ + handled = true; \ + boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \ + epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\ + req.load(ps); \ + boost::uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ + boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \ + epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(resp_); \ + resp.id = req.id; \ + if(!callback_f(req.params, resp.result)) \ +{ \ + epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ + fail_resp.id = req.id; \ + fail_resp.error.code = -32603; \ + fail_resp.error.message = "Internal error"; \ + epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ + return true; \ +} \ + boost::uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ + epee::serialization::store_t_to_json(resp, response_info.m_body); \ + boost::uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ + response_info.m_mime_tipe = "application/json"; \ + response_info.m_header_info.m_content_type = " application/json"; \ + LOG_PRINT( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ + return true;\ +} + + +#define END_JSON_RPC_MAP() \ + epee::json_rpc::error_response rsp; \ + rsp.error.code = -32601; \ + rsp.error.message = "Method not found"; \ + epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \ + return true; \ + } + + |