From 4c4851eeb6fbda9d53860a279e695bd5a01fc290 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Mon, 8 Mar 2021 00:46:44 +0800 Subject: [PATCH] hku server continue --- hikyuu_cpp/hikyuu_server/http/HttpClient.h | 17 ++++++ hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp | 52 +++++++++++++++++ hikyuu_cpp/hikyuu_server/http/HttpHandle.h | 18 ++++++ hikyuu_cpp/hikyuu_server/http/HttpServer.cpp | 21 ++++++- hikyuu_cpp/hikyuu_server/http/url.cpp | 56 +++++++++++++++++++ hikyuu_cpp/hikyuu_server/http/url.h | 17 ++++++ hikyuu_cpp/hikyuu_server/main.cpp | 10 ---- .../hikyuu_server/rest_api/HKUHandle.cpp | 14 ++++- hikyuu_cpp/hikyuu_server/rest_api/login.h | 4 +- 9 files changed, 193 insertions(+), 16 deletions(-) create mode 100644 hikyuu_cpp/hikyuu_server/http/HttpClient.h create mode 100644 hikyuu_cpp/hikyuu_server/http/url.cpp create mode 100644 hikyuu_cpp/hikyuu_server/http/url.h diff --git a/hikyuu_cpp/hikyuu_server/http/HttpClient.h b/hikyuu_cpp/hikyuu_server/http/HttpClient.h new file mode 100644 index 00000000..1d99516f --- /dev/null +++ b/hikyuu_cpp/hikyuu_server/http/HttpClient.h @@ -0,0 +1,17 @@ +/* + * Copyright(C) 2021 hikyuu.org + * + * Create on: 2021-03-07 + * Author: fasiondog + */ + +#pragma once + +namespace hku { + +class HttpClient { +public: + HttpClient() {} +}; + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp b/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp index c07d63ec..59261875 100644 --- a/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp +++ b/hikyuu_cpp/hikyuu_server/http/HttpHandle.cpp @@ -7,6 +7,7 @@ #pragma once +#include "url.h" #include "HttpHandle.h" namespace hku { @@ -87,4 +88,55 @@ std::string HttpHandle::getReqData() { return data ? std::string((char*)data) : std::string(); } +bool HttpHandle::haveQueryParams() { + const char* url = nng_http_req_get_uri(m_nng_req); + return !url ? false : strchr(url, '?'); +} + +bool HttpHandle::getQueryParams(QueryParams& query_params) { + const char* url = nng_http_req_get_uri(m_nng_req); + CLS_IF_RETURN(!url, false); + + const char* p = strchr(url, '?'); + CLS_IF_RETURN(!p, false); + + p = p + 1; + + enum { + s_key, + s_value, + } state = s_key; + + const char* key = p; + const char* value = NULL; + int key_len = 0; + int value_len = 0; + while (*p != '\0') { + if (*p == '&') { + if (key_len && value_len) { + std::string strkey = std::string(key, key_len); + std::string strvalue = std::string(value, value_len); + query_params[url_unescape(strkey.c_str())] = url_unescape(strvalue.c_str()); + key_len = value_len = 0; + } + state = s_key; + key = p + 1; + } else if (*p == '=') { + state = s_value; + value = p + 1; + } else { + state == s_key ? ++key_len : ++value_len; + } + ++p; + } + if (key_len && value_len) { + std::string strkey = std::string(key, key_len); + std::string strvalue = std::string(value, value_len); + query_params[url_unescape(strkey.c_str())] = url_unescape(strvalue.c_str()); + key_len = value_len = 0; + } + + return query_params.size() != 0; +} + } // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu_server/http/HttpHandle.h b/hikyuu_cpp/hikyuu_server/http/HttpHandle.h index aea62bff..18beb422 100644 --- a/hikyuu_cpp/hikyuu_server/http/HttpHandle.h +++ b/hikyuu_cpp/hikyuu_server/http/HttpHandle.h @@ -96,10 +96,28 @@ public: std::string getReqData(); + /** + * 请求的 ulr 中是否包含 query 参数 + */ + bool haveQueryParams(); + + typedef std::unordered_map QueryParams; + + /** + * 获取 query 参数 + * @param query_params [out] 输出 query 参数 + * @return true | false 获取或解析失败 + */ + bool getQueryParams(QueryParams &query_params); + void setResStatus(uint16_t status) { NNG_CHECK(nng_http_res_set_status(m_nng_res, status)); } + void setResHeader(const char *key, const char *val) { + NNG_CHECK(nng_http_res_set_header(m_nng_res, key, val)); + } + void setResData(const std::string_view &content) { NNG_CHECK(nng_http_res_copy_data(m_nng_res, content.data(), content.size())); } diff --git a/hikyuu_cpp/hikyuu_server/http/HttpServer.cpp b/hikyuu_cpp/hikyuu_server/http/HttpServer.cpp index 6c2975bd..e95cfbb9 100644 --- a/hikyuu_cpp/hikyuu_server/http/HttpServer.cpp +++ b/hikyuu_cpp/hikyuu_server/http/HttpServer.cpp @@ -8,6 +8,10 @@ #include #include "HttpServer.h" +#if defined(_WIN32) +#include +#endif + namespace hku { #define HTTP_FATAL_CHECK(rv, msg) \ @@ -21,9 +25,17 @@ namespace hku { nng_http_server* HttpServer::ms_server = nullptr; MQThreadPool HttpServer::ms_tg(std::thread::hardware_concurrency(), false); +#if defined(_WIN32) +static UINT g_old_cp; +#endif + void HttpServer::http_exit() { CLS_INFO("exit server"); - std::this_thread::sleep_for(std::chrono::seconds(1)); + +#if defined(_WIN32) + SetConsoleOutputCP(g_old_cp); +#endif + if (ms_server) { nng_http_server_release(ms_server); nng_fini(); @@ -60,6 +72,13 @@ HttpServer::~HttpServer() { void HttpServer::start() { std::signal(SIGINT, &HttpServer::signal_handler); std::signal(SIGTERM, &HttpServer::signal_handler); + +#if defined(_WIN32) + // Windows 下设置控制台程序输出代码页为 UTF8 + auto g_old_cp = GetConsoleOutputCP(); + SetConsoleOutputCP(CP_UTF8); +#endif + HTTP_FATAL_CHECK(nng_http_server_start(ms_server), "Failed nng_http_server_start!"); } diff --git a/hikyuu_cpp/hikyuu_server/http/url.cpp b/hikyuu_cpp/hikyuu_server/http/url.cpp new file mode 100644 index 00000000..4052ff9d --- /dev/null +++ b/hikyuu_cpp/hikyuu_server/http/url.cpp @@ -0,0 +1,56 @@ +/* + * Copyright(C) 2021 hikyuu.org + * + * Create on: 2021-03-07 + * Author: fasiondog + */ + +#include "url.h" + +namespace hku { + +#define IS_ALPHA(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) +#define IS_NUM(c) ((c) >= '0' && (c) <= '9') +#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) +#define IS_HEX(c) (IS_NUM(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) + +static inline bool is_unambiguous(char c) { + return IS_ALPHANUM(c) || c == '-' || c == '_' || c == '.' || c == '~'; +} + +static inline unsigned char hex2i(char hex) { + return hex <= '9' ? hex - '0' : hex <= 'F' ? hex - 'A' + 10 : hex - 'a' + 10; +} + +std::string url_escape(const char* istr) { + std::string ostr; + const char* p = istr; + char szHex[4] = {0}; + while (*p != '\0') { + if (is_unambiguous(*p)) { + ostr += *p; + } else { + sprintf(szHex, "%%%02X", *p); + ostr += szHex; + } + ++p; + } + return ostr; +} + +std::string url_unescape(const char* istr) { + std::string ostr; + const char* p = istr; + while (*p != '\0') { + if (*p == '%' && IS_HEX(p[1]) && IS_HEX(p[2])) { + ostr += ((hex2i(p[1]) << 4) | hex2i(p[2])); + p += 3; + } else { + ostr += *p; + ++p; + } + } + return ostr; +} + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu_server/http/url.h b/hikyuu_cpp/hikyuu_server/http/url.h new file mode 100644 index 00000000..b4980072 --- /dev/null +++ b/hikyuu_cpp/hikyuu_server/http/url.h @@ -0,0 +1,17 @@ +/* + * Copyright(C) 2021 hikyuu.org + * + * Create on: 2021-03-07 + * Author: fasiondog + */ + +#pragma once + +#include + +namespace hku { + +std::string url_escape(const char* istr); +std::string url_unescape(const char* istr); + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu_server/main.cpp b/hikyuu_cpp/hikyuu_server/main.cpp index 5a328cc7..50dcbfa7 100644 --- a/hikyuu_cpp/hikyuu_server/main.cpp +++ b/hikyuu_cpp/hikyuu_server/main.cpp @@ -18,12 +18,6 @@ using namespace hku; int main(int argc, char* argv[]) { -#if defined(_WIN32) - // Windows 下设置控制台程序输出代码页为 UTF8 - auto old_cp = GetConsoleOutputCP(); - SetConsoleOutputCP(CP_UTF8); -#endif - HKU_INFO("start server ... You can press Ctrl-C stop"); HttpServer server("http://*", 8080); @@ -32,9 +26,5 @@ int main(int argc, char* argv[]) { server.GET("/login"); server.start(); - -#if defined(_WIN32) - SetConsoleOutputCP(old_cp); -#endif return 0; } diff --git a/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp b/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp index 71fa648a..4a63849f 100644 --- a/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp +++ b/hikyuu_cpp/hikyuu_server/rest_api/HKUHandle.cpp @@ -10,20 +10,28 @@ namespace hku { -enum hku_handle_errno { +enum hku_rest_errno { HKU_HANDLE_INVALID_CONTENT = 1, + HKU_HANDLE_MISS_TOKEN = 2, + HKU_HANDLE_UNAUTHORIZED = 3, }; static std::unordered_map g_hku_handle_errmsg{ // clang-format off - {HKU_HANDLE_INVALID_CONTENT, R"(Invalid Content-Type, Please use "application/json")"}, + {HKU_HANDLE_INVALID_CONTENT, "Invalid Content-Type, Please use 'application/json'"}, + {HKU_HANDLE_MISS_TOKEN, "Missing token"}, + {HKU_HANDLE_UNAUTHORIZED, "Authentication failed"}, // clang-format on }; void HKUHandle::before_run() { + setResHeader("Content-Type", "application/json; charset=UTF-8"); + const char *content_type = getReqHeader("Content-Type"); HANDLE_CHECK(content_type, HKU_HANDLE_INVALID_CONTENT); - // application/json + + const char *token = getReqHeader("token"); + HANDLE_CHECK(token, HKU_HANDLE_MISS_TOKEN); } void HKUHandle::error(int errcode) { diff --git a/hikyuu_cpp/hikyuu_server/rest_api/login.h b/hikyuu_cpp/hikyuu_server/rest_api/login.h index 966b6989..1187ee27 100644 --- a/hikyuu_cpp/hikyuu_server/rest_api/login.h +++ b/hikyuu_cpp/hikyuu_server/rest_api/login.h @@ -7,11 +7,11 @@ #pragma once -#include "../http/HttpHandle.h" +#include "HKUHandle.h" namespace hku { -class LoginHandle : public HttpHandle { +class LoginHandle : public HKUHandle { public: LoginHandle(nng_aio *aio) : HttpHandle(aio) {}