Skip to content

Commit bb24b8a

Browse files
committed
support custom http handler chain headerHandler
support http handler chain return HTTP_STATUS_WANT_CLOSE support http server bind onAccept and onClose callback support http legal relative path request optimize http path safe check Performance and Process optimize http server path file cache map key fix hv_parse_url processing '#' and '?' order priority bug fix false positives '/..file' normal path bug add hv_normalize_path function to hbase.h fix defaultLargeFileHandler not support chinese path add windows hv::utf8_to_ansi and hv::ansi_to_utf8 function to hstring.h optimize some log level and msg desc
1 parent 7ba055f commit bb24b8a

18 files changed

Lines changed: 212 additions & 72 deletions

File tree

base/hbase.c

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -521,22 +521,84 @@ int hv_parse_url(hurl_t* stURL, const char* strURL) {
521521
if (ep == end) return 0;
522522
// /path
523523
sp = ep;
524-
ep = strchr(sp, '?');
525-
if (ep == NULL) ep = end;
524+
const char* query = strchr(sp, '?');
525+
const char* fragment = strchr(sp, '#');
526+
if (query && fragment) ep = MIN(query, fragment);
527+
else if (query == NULL && fragment) ep = fragment;
528+
else if (query == NULL) ep = end;
529+
else ep = query;
526530
stURL->fields[HV_URL_PATH].off = sp - begin;
527531
stURL->fields[HV_URL_PATH].len = ep - sp;
528532
if (ep == end) return 0;
529-
// ?query
530-
sp = ep + 1;
531-
ep = strchr(sp, '#');
532-
if (ep == NULL) ep = end;
533-
stURL->fields[HV_URL_QUERY].off = sp - begin;
534-
stURL->fields[HV_URL_QUERY].len = ep - sp;
535-
if (ep == end) return 0;
533+
if (ep != fragment) {
534+
// ?query
535+
sp = ep + 1;
536+
ep = fragment;
537+
if (ep == NULL) ep = end;
538+
stURL->fields[HV_URL_QUERY].off = sp - begin;
539+
stURL->fields[HV_URL_QUERY].len = ep - sp;
540+
if (ep == end) return 0;
541+
}
536542
// #fragment
537543
sp = ep + 1;
538544
ep = end;
539545
stURL->fields[HV_URL_FRAGMENT].off = sp - begin;
540546
stURL->fields[HV_URL_FRAGMENT].len = ep - sp;
541547
return 0;
542548
}
549+
550+
int hv_normalize_path(char *path) {
551+
if (*path != '/') return 0;
552+
int pos = 1;
553+
#ifdef OS_WIN
554+
int sum = 0;
555+
#endif
556+
for (int i = 1; path[i] != '\0'; ++i) {
557+
switch (path[i]) {
558+
case '\\':
559+
case '/':
560+
if (path[pos - 1] != '/') path[pos++] = '/';
561+
break;
562+
563+
case '.':
564+
if (path[pos - 1] == '/') {
565+
if (path[i + 1] == '.' && (path[i + 2] == '/' || path[i + 2] == '\\' || path[i + 2] == '\0')) {
566+
while (--pos > 0) {
567+
if (path[pos - 1] == '/') break;
568+
}
569+
if (pos < 1) return 0;
570+
i += path[i + 2] == '\0' ? 1 : 2;
571+
break;
572+
}
573+
if (path[i + 1] == '\0') break;
574+
if (path[i + 1] == '/' || path[i + 1] == '\\') {
575+
++i;
576+
break;
577+
}
578+
}
579+
path[pos++] = '.';
580+
#ifdef OS_WIN
581+
// windows does not have a trailing '.'
582+
sum = 1;
583+
while (path[i + sum] == '.') {
584+
path[pos++] = '.';
585+
++sum;
586+
}
587+
if (path[i + sum] == '\0') pos -= sum;
588+
i += sum - 1;
589+
#endif
590+
break;
591+
592+
default:
593+
#ifdef OS_WIN
594+
// windows is not case sensitive
595+
path[pos++] = (char)tolower(path[i]);
596+
#else
597+
path[pos++] = path[i];
598+
#endif
599+
break;
600+
}
601+
}
602+
path[pos] = '\0';
603+
return pos;
604+
}

base/hbase.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ typedef struct hurl_s {
140140

141141
HV_EXPORT int hv_parse_url(hurl_t* stURL, const char* strURL);
142142

143+
HV_EXPORT int hv_normalize_path(char *path);
144+
143145
END_EXTERN_C
144146

145147
#endif // HV_BASE_H_

cpputil/hstring.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,24 +226,25 @@ std::string NetAddr::to_string(const char* ip, int port) {
226226
}
227227

228228
#ifdef OS_WIN
229-
std::string wchar_to_utf8(const std::wstring &wstr) {
229+
std::string wchar_to_string(const UINT codePage, const std::wstring &wstr) {
230230
std::string str(4 * wstr.size() + 1, '\0');
231231
str.resize(WideCharToMultiByte(
232-
CP_UTF8, 0,
233-
wstr.c_str(), wstr.size(),
234-
const_cast<char*>(str.data()), str.size(),
232+
codePage, 0,
233+
wstr.c_str(), wstr.size(),
234+
const_cast<char*>(str.data()), str.size(),
235235
NULL, NULL));
236236
return str;
237237
}
238238

239-
std::wstring utf8_to_wchar(const std::string &str) {
240-
std::wstring wstr(2 * str.size() + 1, '\0');
239+
std::wstring string_to_wchar(const UINT codePage, const std::string &str) {
240+
std::wstring wstr(2 * str.size() + 2, '\0');
241241
wstr.resize(MultiByteToWideChar(
242-
CP_UTF8, 0,
243-
str.c_str(), str.size(),
242+
codePage, 0,
243+
str.c_str(), str.size(),
244244
const_cast<wchar_t*>(wstr.data()), wstr.size()));
245245
return wstr;
246246
}
247+
247248
#endif // OS_WIN
248249

249250
} // end namespace hv

cpputil/hstring.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,31 @@ struct HV_EXPORT NetAddr {
8888
static std::string to_string(const char* ip, int port);
8989
};
9090

91-
// windows wchar and utf8 conver
91+
// windows wchar and utf8/ansi conver
9292
#ifdef OS_WIN
93-
HV_EXPORT std::string wchar_to_utf8(const std::wstring &wstr);
94-
HV_EXPORT std::wstring utf8_to_wchar(const std::string &str);
93+
HV_EXPORT std::string wchar_to_string(const UINT codePage, const std::wstring &wstr);
94+
HV_EXPORT std::wstring string_to_wchar(const UINT codePage, const std::string &str);
95+
96+
HV_INLINE std::string wchar_to_utf8(const std::wstring &wstr) {
97+
return wchar_to_string(CP_UTF8, wstr);
98+
}
99+
100+
HV_INLINE std::string wchar_to_ansi(const std::wstring &wstr) {
101+
return wchar_to_string(CP_ACP, wstr);
102+
}
103+
104+
HV_INLINE std::wstring utf8_to_wchar(const std::string &str) {
105+
return string_to_wchar(CP_UTF8, str);
106+
}
107+
108+
HV_INLINE std::string utf8_to_ansi(const std::string &str) {
109+
return wchar_to_string(CP_ACP, string_to_wchar(CP_UTF8, str));
110+
}
111+
112+
HV_INLINE std::string ansi_to_utf8(const std::string &str) {
113+
return wchar_to_string(CP_UTF8, string_to_wchar(CP_ACP, str));
114+
}
115+
95116
#endif // OS_WIN
96117

97118
} // end namespace hv

docs/cn/HttpServer.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ class HttpService {
9393
// 返回注册的路由路径列表
9494
hv::StringList Paths();
9595

96-
// 处理流程:前处理器 -> 中间件 -> 处理器 -> 后处理器
97-
// preprocessor -> middleware -> processor -> postprocessor
96+
// 处理流程:标头处理器 -> 前处理器 -> 中间件 -> 处理器 -> 后处理器
97+
// headerHandler -> preprocessor -> middleware -> processor -> postprocessor
9898

9999
// 数据成员
100+
http_handler headerHandler; // 标头处理器
100101
http_handler preprocessor; // 前处理器
101102
http_handlers middleware; // 中间件
102103
http_handler processor; // 处理器

event/hevent.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ static void __write_timeout_cb(htimer_t* timer) {
602602
if (io->io_type & HIO_TYPE_SOCKET) {
603603
char localaddrstr[SOCKADDR_STRLEN] = {0};
604604
char peeraddrstr[SOCKADDR_STRLEN] = {0};
605-
hlogw("write timeout [%s] <=> [%s]",
605+
hlogi("write timeout [%s] <=> [%s]",
606606
SOCKADDR_STR(io->localaddr, localaddrstr),
607607
SOCKADDR_STR(io->peeraddr, peeraddrstr));
608608
}

event/nio.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static void ssl_server_handshake(hio_t* io) {
8080
}
8181
}
8282
else {
83-
hloge("ssl handshake failed: %d", ret);
83+
hloge("ssl server handshake failed: %d", ret);
8484
io->error = ERR_SSL_HANDSHAKE;
8585
hio_close(io);
8686
}
@@ -101,7 +101,7 @@ static void ssl_client_handshake(hio_t* io) {
101101
}
102102
}
103103
else {
104-
hloge("ssl handshake failed: %d", ret);
104+
hloge("ssl client handshake failed: %d", ret);
105105
io->error = ERR_SSL_HANDSHAKE;
106106
hio_close(io);
107107
}

examples/httpd/handler.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@
99
#include "hstring.h"
1010
#include "EventLoop.h" // import setTimeout, setInterval
1111

12-
int Handler::preprocessor(HttpRequest* req, HttpResponse* resp) {
12+
int Handler::headerHandler(HttpRequest* req, HttpResponse* resp) {
1313
// printf("%s:%d\n", req->client_addr.ip.c_str(), req->client_addr.port);
14-
// printf("%s\n", req->Dump(true, true).c_str());
15-
1614
#if REDIRECT_HTTP_TO_HTTPS
1715
// 301
1816
if (req->scheme == "http") {
@@ -25,6 +23,11 @@ int Handler::preprocessor(HttpRequest* req, HttpResponse* resp) {
2523
// if (req->content_type != APPLICATION_JSON) {
2624
// return response_status(resp, HTTP_STATUS_BAD_REQUEST);
2725
// }
26+
return HTTP_STATUS_NEXT;
27+
}
28+
29+
int Handler::preprocessor(HttpRequest* req, HttpResponse* resp) {
30+
// printf("%s\n", req->Dump(true, true).c_str());
2831

2932
// Deserialize request body to json, form, etc.
3033
req->ParseBody();

examples/httpd/handler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
class Handler {
77
public:
8-
// preprocessor => middleware -> handlers => postprocessor
8+
// headerHandler => preprocessor => middleware -> handlers => postprocessor
9+
static int headerHandler(HttpRequest* req, HttpResponse* resp);
910
static int preprocessor(HttpRequest* req, HttpResponse* resp);
1011
static int postprocessor(HttpRequest* req, HttpResponse* resp);
1112
static int errorHandler(const HttpContextPtr& ctx);

examples/httpd/router.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
void Router::Register(hv::HttpService& router) {
99
/* handler chain */
10-
// preprocessor -> middleware -> processor -> postprocessor
10+
// headerHandler -> preprocessor -> middleware -> processor -> postprocessor
1111
// processor: pathHandlers -> staticHandler -> errorHandler
12+
router.headerHandler = Handler::headerHandler;
1213
router.preprocessor = Handler::preprocessor;
1314
router.postprocessor = Handler::postprocessor;
1415
// router.errorHandler = Handler::errorHandler;

0 commit comments

Comments
 (0)