2021-03-01 00:58:36 +08:00
|
|
|
/*
|
|
|
|
* Copyright(C) 2021 hikyuu.org
|
|
|
|
*
|
|
|
|
* Create on: 2021-02-28
|
|
|
|
* Author: fasiondog
|
|
|
|
*/
|
|
|
|
|
2021-03-08 00:46:44 +08:00
|
|
|
#include "url.h"
|
2021-03-01 00:58:36 +08:00
|
|
|
#include "HttpHandle.h"
|
|
|
|
|
|
|
|
namespace hku {
|
|
|
|
|
2021-03-06 01:05:31 +08:00
|
|
|
HttpHandle::HttpHandle(nng_aio* aio) : m_http_aio(aio) {}
|
2021-03-01 00:58:36 +08:00
|
|
|
|
|
|
|
void HttpHandle::operator()() {
|
2021-03-06 01:05:31 +08:00
|
|
|
CLS_FATAL_IF_RETURN(!m_http_aio, void(), "http aio is null!");
|
|
|
|
int rv = nng_http_res_alloc(&m_nng_res);
|
|
|
|
if (rv != 0) {
|
|
|
|
CLS_FATAL("Failed nng_http_res_alloc! {}", nng_strerror(rv));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-01 00:58:36 +08:00
|
|
|
try {
|
|
|
|
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);
|
|
|
|
|
2021-03-14 01:32:19 +08:00
|
|
|
for (auto& filter : m_filters) {
|
|
|
|
filter(this);
|
|
|
|
}
|
|
|
|
|
2021-03-07 18:14:04 +08:00
|
|
|
before_run();
|
2021-03-01 00:58:36 +08:00
|
|
|
run();
|
|
|
|
|
|
|
|
nng_aio_set_output(m_http_aio, 0, m_nng_res);
|
|
|
|
nng_aio_finish(m_http_aio, 0);
|
|
|
|
|
2021-03-14 12:09:47 +08:00
|
|
|
} catch (HttpError& e) {
|
2021-03-14 01:32:19 +08:00
|
|
|
nng_http_res_set_status(m_nng_res, e.status());
|
2021-03-14 19:22:32 +08:00
|
|
|
nng_http_res_set_reason(m_nng_res, e.msg().c_str());
|
|
|
|
CLS_WARN_IF(nng_http_res_copy_data(m_nng_res, e.msg().c_str(), e.msg().size()),
|
2021-03-14 01:32:19 +08:00
|
|
|
"Failed nng_http_res_copy_data!");
|
2021-03-07 18:14:04 +08:00
|
|
|
nng_aio_set_output(m_http_aio, 0, m_nng_res);
|
|
|
|
nng_aio_finish(m_http_aio, 0);
|
|
|
|
|
2021-03-01 00:58:36 +08:00
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::string errmsg(e.what());
|
2021-03-05 00:59:11 +08:00
|
|
|
CLS_ERROR(errmsg);
|
2021-03-07 18:14:04 +08:00
|
|
|
unknown_error(errmsg);
|
2021-03-01 00:58:36 +08:00
|
|
|
|
|
|
|
} catch (...) {
|
|
|
|
std::string errmsg("Unknown error!");
|
2021-03-05 00:59:11 +08:00
|
|
|
CLS_ERROR(errmsg);
|
2021-03-07 18:14:04 +08:00
|
|
|
unknown_error(errmsg);
|
2021-03-01 00:58:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 18:14:04 +08:00
|
|
|
void HttpHandle::unknown_error(const std::string& errmsg) {
|
2021-03-06 01:05:31 +08:00
|
|
|
try {
|
|
|
|
int errcode = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
|
|
|
const char* info = "Internal server error!";
|
|
|
|
std::string html_template(
|
|
|
|
R"(<!DOCTYPE html>
|
|
|
|
<html><head><title>{} {}</title>
|
|
|
|
<style>"
|
|
|
|
body {{ font-family: Arial, sans serif; text-align: center }}
|
|
|
|
h1 {{ font-size: 36px; }}
|
|
|
|
span {{ background-color: gray; color: white; padding: 7px; border-radius: 5px }}
|
|
|
|
h2 {{ font-size: 24px; }}
|
|
|
|
p {{ font-size: 20px; }}
|
|
|
|
</style></head>
|
|
|
|
<body><p> </p>
|
|
|
|
<h1><span>{}</span></h1>
|
|
|
|
<h2>{}</h2>
|
|
|
|
<p>{}</p>
|
|
|
|
</body></html>)");
|
|
|
|
std::string html = fmt::format(html_template, errcode, info, errcode, info, errmsg);
|
|
|
|
nng_http_res_set_status(m_nng_res, errcode);
|
|
|
|
nng_http_res_set_reason(m_nng_res, errmsg.c_str());
|
|
|
|
nng_http_res_set_header(m_nng_res, "Content-Type", "text/html; charset=UTF-8");
|
2021-03-14 01:32:19 +08:00
|
|
|
CLS_WARN_IF(nng_http_res_copy_data(m_nng_res, html.c_str(), html.size()),
|
|
|
|
"Failed nng_http_res_copy_data!");
|
2021-03-06 01:05:31 +08:00
|
|
|
nng_aio_set_output(m_http_aio, 0, m_nng_res);
|
|
|
|
nng_aio_finish(m_http_aio, 0);
|
|
|
|
} catch (...) {
|
2021-03-07 18:14:04 +08:00
|
|
|
CLS_FATAL("unknown error in finished!");
|
2021-03-06 01:05:31 +08:00
|
|
|
}
|
2021-03-01 00:58:36 +08:00
|
|
|
}
|
|
|
|
|
2021-03-07 18:14:04 +08:00
|
|
|
std::string HttpHandle::getReqData() {
|
2021-03-07 01:17:40 +08:00
|
|
|
void* data = nullptr;
|
|
|
|
size_t len = 0;
|
|
|
|
nng_http_req_get_data(m_nng_req, &data, &len);
|
|
|
|
return data ? std::string((char*)data) : std::string();
|
|
|
|
}
|
|
|
|
|
2021-03-08 00:46:44 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-03-01 00:58:36 +08:00
|
|
|
} // namespace hku
|