Go to the documentation of this file. 34 #undef MONERO_DEFAULT_LOG_CATEGORY 35 #define MONERO_DEFAULT_LOG_CATEGORY "net.http" 38 #define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ 39 epee::net_utils::http::http_response_info& response, \ 40 context_type& m_conn_context) \ 42 MINFO("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ 43 response.m_response_code = 200; \ 44 response.m_response_comment = "Ok"; \ 47 if(!handle_http_request_map(query_info, response, m_conn_context)) \ 48 {response.m_response_code = 404;response.m_response_comment = "Not found";} \ 50 catch (const std::exception &e) \ 52 MERROR(m_conn_context << "Exception in handle_http_request_map: " << e.what()); \ 53 response.m_response_code = 500; \ 54 response.m_response_comment = "Internal Server Error"; \ 60 #define BEGIN_URI_MAP2() template<class t_context> bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \ 61 epee::net_utils::http::http_response_info& response_info, \ 62 t_context& m_conn_context) { \ 63 bool handled = false; \ 64 if(false) return true; //just a stub to have "else if" 66 #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); 68 #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 70 #define MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, cond) \ 71 else if((query_info.m_URI == s_pattern) && (cond)) \ 74 uint64_t ticks = epee::misc_utils::get_tick_count(); \ 75 boost::value_initialized<command_type::request> req; \ 76 bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \ 79 MERROR("Failed to parse json: \r\n" << query_info.m_body); \ 80 response_info.m_response_code = 400; \ 81 response_info.m_response_comment = "Bad request"; \ 84 uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ 85 boost::value_initialized<command_type::response> resp;\ 86 MINFO(m_conn_context << "calling " << s_pattern); \ 88 try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \ 89 catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \ 92 response_info.m_response_code = 500; \ 93 response_info.m_response_comment = "Internal Server Error"; \ 96 uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ 97 epee::serialization::store_t_to_json(static_cast<command_type::response&>(resp), response_info.m_body); \ 98 uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ 99 response_info.m_mime_tipe = "application/json"; \ 100 response_info.m_header_info.m_content_type = " application/json"; \ 101 MDEBUG( s_pattern << " processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \ 104 #define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, true) 106 #define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \ 107 else if(query_info.m_URI == s_pattern) \ 110 uint64_t ticks = epee::misc_utils::get_tick_count(); \ 111 boost::value_initialized<command_type::request> req; \ 112 bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), epee::strspan<uint8_t>(query_info.m_body)); \ 115 MERROR("Failed to parse bin body data, body size=" << query_info.m_body.size()); \ 116 response_info.m_response_code = 400; \ 117 response_info.m_response_comment = "Bad request"; \ 120 uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ 121 boost::value_initialized<command_type::response> resp;\ 122 MINFO(m_conn_context << "calling " << s_pattern); \ 124 try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \ 125 catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "()"); } \ 128 response_info.m_response_code = 500; \ 129 response_info.m_response_comment = "Internal Server Error"; \ 132 uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ 133 epee::byte_slice buffer; \ 134 epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), buffer, 64 * 1024); \ 135 uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ 136 response_info.m_body.assign(reinterpret_cast<const char*>(buffer.data()), buffer.size()); \ 137 response_info.m_mime_tipe = " application/octet-stream"; \ 138 response_info.m_header_info.m_content_type = " application/octet-stream"; \ 139 MDEBUG( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \ 142 #define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);handled = true;} 144 #define END_URI_MAP2() return handled;} 147 #define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \ 149 uint64_t ticks = epee::misc_utils::get_tick_count(); \ 150 response_info.m_mime_tipe = "application/json"; \ 151 epee::serialization::portable_storage ps; \ 152 if(!ps.load_from_json(query_info.m_body)) \ 154 boost::value_initialized<epee::json_rpc::error_response> rsp; \ 155 static_cast<epee::json_rpc::error_response&>(rsp).jsonrpc = "2.0"; \ 156 static_cast<epee::json_rpc::error_response&>(rsp).error.code = -32700; \ 157 static_cast<epee::json_rpc::error_response&>(rsp).error.message = "Parse error"; \ 158 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \ 161 epee::serialization::storage_entry id_; \ 162 id_ = epee::serialization::storage_entry(std::string()); \ 163 ps.get_value("id", id_, nullptr); \ 164 std::string callback_name; \ 165 if(!ps.get_value("method", callback_name, nullptr)) \ 167 epee::json_rpc::error_response rsp; \ 168 rsp.jsonrpc = "2.0"; \ 169 rsp.error.code = -32600; \ 170 rsp.error.message = "Invalid Request"; \ 171 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \ 174 epee::serialization::storage_entry params_; \ 175 params_ = epee::serialization::storage_entry(epee::serialization::section()); \ 176 if(!ps.get_value("params", params_, nullptr)) \ 178 epee::serialization::section params_section; \ 179 ps.set_value("params", std::move(params_section), nullptr); \ 181 if(false) return true; //just a stub to have "else if" 184 #define PREPARE_OBJECTS_FROM_JSON(command_type) \ 186 response_info.m_mime_tipe = "application/json"; \ 187 boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \ 188 epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\ 191 epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ 192 fail_resp.jsonrpc = "2.0"; \ 193 fail_resp.id = req.id; \ 194 fail_resp.error.code = -32602; \ 195 fail_resp.error.message = "Invalid params"; \ 196 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ 199 uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ 200 boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \ 201 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_); \ 202 resp.jsonrpc = "2.0"; \ 205 #define FINALIZE_OBJECTS_TO_JSON(method_name) \ 206 uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ 207 epee::serialization::store_t_to_json(resp, response_info.m_body); \ 208 uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ 209 response_info.m_mime_tipe = "application/json"; \ 210 response_info.m_header_info.m_content_type = " application/json"; \ 211 MDEBUG( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); 213 #define MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, cond) \ 214 else if((callback_name == method_name) && (cond)) \ 216 PREPARE_OBJECTS_FROM_JSON(command_type) \ 217 epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ 218 fail_resp.jsonrpc = "2.0"; \ 219 fail_resp.id = req.id; \ 220 MINFO(m_conn_context << "Calling RPC method " << method_name); \ 222 try { res = callback_f(req.params, resp.result, fail_resp.error, &m_conn_context); } \ 223 catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \ 226 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ 229 FINALIZE_OBJECTS_TO_JSON(method_name) \ 233 #define MAP_JON_RPC_WE(method_name, callback_f, command_type) MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, true) 235 #define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \ 236 else if(callback_name == method_name) \ 238 PREPARE_OBJECTS_FROM_JSON(command_type) \ 239 epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ 240 fail_resp.jsonrpc = "2.0"; \ 241 fail_resp.id = req.id; \ 242 MINFO(m_conn_context << "calling RPC method " << method_name); \ 244 try { res = callback_f(req.params, resp.result, fail_resp.error, response_info, &m_conn_context); } \ 245 catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \ 248 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ 251 FINALIZE_OBJECTS_TO_JSON(method_name) \ 255 #define MAP_JON_RPC(method_name, callback_f, command_type) \ 256 else if(callback_name == method_name) \ 258 PREPARE_OBJECTS_FROM_JSON(command_type) \ 259 MINFO(m_conn_context << "calling RPC method " << method_name); \ 261 try { res = callback_f(req.params, resp.result, &m_conn_context); } \ 262 catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \ 265 epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ 266 fail_resp.jsonrpc = "2.0"; \ 267 fail_resp.id = req.id; \ 268 fail_resp.error.code = -32603; \ 269 fail_resp.error.message = "Internal error"; \ 270 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \ 273 FINALIZE_OBJECTS_TO_JSON(method_name) \ 277 #define END_JSON_RPC_MAP() \ 278 epee::json_rpc::error_response rsp; \ 280 rsp.jsonrpc = "2.0"; \ 281 rsp.error.code = -32601; \ 282 rsp.error.message = "Method not found"; \ 283 epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \