diff --git a/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp b/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp index 6a7ed25b..c07d63ec 100644 --- a/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp +++ b/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp @@ -25,24 +25,31 @@ void HttpHandle::operator()() { m_nng_req = (nng_http_req*)nng_aio_get_input(m_http_aio, 0); m_nng_conn = (nng_http_conn*)nng_aio_get_input(m_http_aio, 2); + before_run(); run(); + // after_run(); nng_aio_set_output(m_http_aio, 0, m_nng_res); nng_aio_finish(m_http_aio, 0); + } catch (HttpHandleRunException& e) { + error(e.errcode()); + nng_aio_set_output(m_http_aio, 0, m_nng_res); + nng_aio_finish(m_http_aio, 0); + } catch (std::exception& e) { std::string errmsg(e.what()); CLS_ERROR(errmsg); - error(errmsg); + unknown_error(errmsg); } catch (...) { std::string errmsg("Unknown error!"); CLS_ERROR(errmsg); - error(errmsg); + unknown_error(errmsg); } } -void HttpHandle::error(const std::string& errmsg) { +void HttpHandle::unknown_error(const std::string& errmsg) { try { int errcode = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; const char* info = "Internal server error!"; @@ -69,10 +76,11 @@ void HttpHandle::error(const std::string& errmsg) { nng_aio_set_output(m_http_aio, 0, m_nng_res); nng_aio_finish(m_http_aio, 0); } catch (...) { + CLS_FATAL("unknown error in finished!"); } } -std::string HttpHandle::getRequestData() { +std::string HttpHandle::getReqData() { void* data = nullptr; size_t len = 0; nng_http_req_get_data(m_nng_req, &data, &len); diff --git a/hikyuu_cpp/hikyuu_server/http/HttpHandle.h b/hikyuu_cpp/hikyuu_server/http/HttpHandle.h index 3043713b..aea62bff 100644 --- a/hikyuu_cpp/hikyuu_server/http/HttpHandle.h +++ b/hikyuu_cpp/hikyuu_server/http/HttpHandle.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -15,6 +16,31 @@ namespace hku { +/** + * 处理异常 + */ +class HttpHandleRunException : public std::exception { +public: + explicit HttpHandleRunException(int errcode) : std::exception(), m_errcode(errcode) {} + + int errcode() const { + return m_errcode; + } + +private: + int m_errcode = 0; +}; + +#define HANDLE_ERROR(errcode) throw HttpHandleRunException(errcode) + +#define HANDLE_CHECK(expr, errcode) \ + do { \ + if (!expr) { \ + throw HttpHandleRunException(errcode); \ + } \ + } while (0) + +// 仅内部使用 #define NNG_CHECK(rv) \ { \ if (rv != 0) { \ @@ -22,6 +48,7 @@ namespace hku { } \ } +// 仅内部使用 #define NNG_CHECK_M(rv, msg) \ { \ if (rv != 0) { \ @@ -36,28 +63,52 @@ public: HttpHandle() = delete; HttpHandle(nng_aio *aio); - virtual void run() { - logger()->warn("Not implemented HttpHandle run method!"); + /** 前处理 */ + virtual void before_run() {} + + /** 响应处理 */ + virtual void run() = 0; + + // virtual void after_run() {} + + /** 统一处理响应错误 */ + virtual void error(int errcode) { + unknown_error(fmt::format("error: {}", errcode)); } - void getRequestData(void **data, size_t *len) { + /** + * 获取请求头部信息 + * @param name 头部信息名称 + * @return 如果获取不到将返回 NULL + */ + const char *getReqHeader(const char *name) { + return nng_http_req_get_header(m_nng_req, name); + } + + std::string getReqHeader(const std::string &name) { + const char *head = nng_http_req_get_header(m_nng_req, name.c_str()); + return head ? std::string(head) : std::string(); + } + + void getReqData(void **data, size_t *len) { nng_http_req_get_data(m_nng_req, data, len); } - std::string getRequestData(); + std::string getReqData(); - void setResponseStatus(uint16_t status) { + void setResStatus(uint16_t status) { NNG_CHECK(nng_http_res_set_status(m_nng_res, status)); } - void setResponseData(const std::string &content) { - NNG_CHECK(nng_http_res_copy_data(m_nng_res, content.c_str(), content.size())); + void setResData(const std::string_view &content) { + NNG_CHECK(nng_http_res_copy_data(m_nng_res, content.data(), content.size())); } void operator()(); private: - void error(const std::string &errmsg); + // error未捕获的信息,统一返回500页面 + void unknown_error(const std::string &errmsg); protected: nng_aio *m_http_aio{nullptr}; diff --git a/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp b/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp new file mode 100644 index 00000000..71fa648a --- /dev/null +++ b/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp @@ -0,0 +1,41 @@ +/* + * Copyright(C) 2021 hikyuu.org + * + * Create on: 2021-03-07 + * Author: fasiondog + */ + +#include +#include "HKUHandle.h" + +namespace hku { + +enum hku_handle_errno { + HKU_HANDLE_INVALID_CONTENT = 1, +}; + +static std::unordered_map g_hku_handle_errmsg{ + // clang-format off + {HKU_HANDLE_INVALID_CONTENT, R"(Invalid Content-Type, Please use "application/json")"}, + // clang-format on +}; + +void HKUHandle::before_run() { + const char *content_type = getReqHeader("Content-Type"); + HANDLE_CHECK(content_type, HKU_HANDLE_INVALID_CONTENT); + // application/json +} + +void HKUHandle::error(int errcode) { + auto iter = g_hku_handle_errmsg.find(errcode); + if (iter == g_hku_handle_errmsg.end()) { + private_error(errcode); + return; + } + + // http 响应状态设为 400 + setResStatus(NNG_HTTP_STATUS_BAD_REQUEST); + setResData(fmt::format(R"({{"error": "{}", "msg": "{}"}})", errcode, iter->second)); +} + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.h b/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.h new file mode 100644 index 00000000..92128196 --- /dev/null +++ b/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.h @@ -0,0 +1,27 @@ +/* + * Copyright(C) 2021 hikyuu.org + * + * Create on: 2021-03-07 + * Author: fasiondog + */ + +#pragma once + +#include "../http/HttpHandle.h" + +namespace hku { + +class HKUHandle : public HttpHandle { + CLASS_LOGGER(HKUHandle) + +public: + HKUHandle(nng_aio *aio) : HttpHandle(aio) {} + + virtual void before_run() override; + + void error(int errcode) override; + + virtual void private_error(int errcode) {} +}; + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu_server/rest_api/hello.h b/hikyuu_cpp/hikyuu_server/rest_api/hello.h index 1dde0003..f5004d70 100644 --- a/hikyuu_cpp/hikyuu_server/rest_api/hello.h +++ b/hikyuu_cpp/hikyuu_server/rest_api/hello.h @@ -7,16 +7,16 @@ #pragma once -#include "../http/HttpHandle.h" +#include "HKUHandle.h" namespace hku { -class HelloHandle : public HttpHandle { +class HelloHandle : public HKUHandle { public: - HelloHandle(nng_aio *aio) : HttpHandle(aio) {} + HelloHandle(nng_aio *aio) : HKUHandle(aio) {} virtual void run() override { - setResponseData("hello"); + setResData("hello"); } }; diff --git a/hikyuu_cpp/hikyuu_server/rest_api/login.h b/hikyuu_cpp/hikyuu_server/rest_api/login.h index cc87ae7a..966b6989 100644 --- a/hikyuu_cpp/hikyuu_server/rest_api/login.h +++ b/hikyuu_cpp/hikyuu_server/rest_api/login.h @@ -16,12 +16,12 @@ public: LoginHandle(nng_aio *aio) : HttpHandle(aio) {} virtual void run() override { - std::string content = getRequestData(); + std::string content = getReqData(); if (content.empty()) { - setResponseStatus(NNG_HTTP_STATUS_NO_CONTENT); + setResStatus(NNG_HTTP_STATUS_BAD_REQUEST); return; } - setResponseData(content); + setResData(content); } }; diff --git a/hikyuu_cpp/hikyuu_server/xmake.lua b/hikyuu_cpp/hikyuu_server/xmake.lua index 34d65cae..318e2786 100644 --- a/hikyuu_cpp/hikyuu_server/xmake.lua +++ b/hikyuu_cpp/hikyuu_server/xmake.lua @@ -1,8 +1,8 @@ -target("hikyuu_server") +target("hkuserver") set_kind("binary") - add_packages("fmt", "spdlog", "flatbuffers", "nng") + add_packages("fmt", "spdlog", "flatbuffers", "nng", "yyjson") add_deps("hikyuu") add_includedirs("..") diff --git a/xmake.lua b/xmake.lua index c75b8259..a5f93b9e 100644 --- a/xmake.lua +++ b/xmake.lua @@ -40,6 +40,7 @@ add_requires("fmt", {system=false, configs = {header_only = true, vs_runtime = " add_requires("spdlog", {system=false, configs = {header_only = true, fmt_external=true, vs_runtime = "MD"}}) add_requires("flatbuffers", {system=false, configs = {vs_runtime="MD"}}) add_requires("nng", {system=false, configs = {vs_runtime="MD"}}) +add_requires("yyjson", {system=false, configs = {vs_runtime="MD"}}) add_defines("SPDLOG_DISABLE_DEFAULT_LOGGER") -- 禁用 spdlog 默认 logger