corecdtl 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt ADDED
@@ -0,0 +1,50 @@
1
+ cmake_minimum_required(VERSION 3.9)
2
+ cmake_policy(SET CMP0042 NEW)
3
+ set (CMAKE_CXX_STANDARD 14)
4
+ if(NOT CMAKE_BUILD_TYPE)
5
+ set(CMAKE_BUILD_TYPE Release)
6
+ endif()
7
+
8
+ project(hypernode)
9
+ include_directories(${CMAKE_JS_INC})
10
+ include_directories(
11
+ ${CMAKE_SOURCE_DIR}/native/include
12
+ ${CMAKE_SOURCE_DIR}/native/http/core
13
+ ${CMAKE_SOURCE_DIR}/native/http/routes
14
+ ${CMAKE_SOURCE_DIR}/native/http/parser
15
+ ${CMAKE_SOURCE_DIR}/native/http/cpool
16
+ )
17
+
18
+ include_directories(${CMAKE_SOURCE_DIR}/native/third_party/simdjson)
19
+
20
+ file(GLOB MAIN_SOURCE "native/main.cpp")
21
+ file(GLOB HTTP_SOURCES "native/http/core/*.cpp")
22
+ file(GLOB ROUTE_BUILDER_SOURCES "native/http/routes/*.cpp")
23
+ file(GLOB CHUNK_PROGRESSION_POOL_SOURCES "native/http/cpool/*.cpp")
24
+ file(GLOB PARSER_SOURCES "native/http/parser/*.cpp")
25
+ file(GLOB SIMDJSON_SOURCES "native/third_party/simdjson/*.cpp")
26
+
27
+ add_library(${PROJECT_NAME} SHARED
28
+ ${MAIN_SOURCE}
29
+ ${ROUTE_BUILDER_SOURCES}
30
+ ${CHUNK_PROGRESSION_POOL_SOURCES}
31
+ ${PARSER_SOURCES}
32
+ ${HTTP_SOURCES}
33
+ ${SIMDJSON_SOURCES}
34
+ ${CMAKE_JS_SRC}
35
+ )
36
+ set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
37
+ target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
38
+
39
+ # Include N-API wrappers
40
+ execute_process(
41
+ COMMAND node -p "require('node-addon-api').include"
42
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
43
+ OUTPUT_VARIABLE NODE_ADDON_API_DIR
44
+ )
45
+ string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
46
+ string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
47
+ target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
48
+
49
+ # define NAPI_VERSION
50
+ add_definitions(-DNAPI_VERSION=3)
package/binding.gyp ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "hypernode",
5
+
6
+ "sources": [
7
+ "native/main.cpp",
8
+
9
+ "native/http/core/*.cpp",
10
+ "native/http/routes/*.cpp",
11
+ "native/http/parser/*.cpp",
12
+ "native/http/cpool/*.cpp",
13
+
14
+ "native/third_party/simdjson/*.cpp"
15
+ ],
16
+
17
+ "include_dirs": [
18
+ "<!(node -p \"require('node-addon-api').include\")",
19
+ "native/include",
20
+ "native/http/core",
21
+ "native/http/routes",
22
+ "native/http/parser",
23
+ "native/http/cpool",
24
+ "native/third_party/simdjson"
25
+ ],
26
+
27
+ "defines": [
28
+ "NAPI_VERSION=3",
29
+ "NAPI_CPP_EXCEPTIONS"
30
+ ],
31
+
32
+ "cflags_cc": [
33
+ "-std=c++17",
34
+ "-O3"
35
+ ],
36
+
37
+ "conditions": [
38
+ ["OS=='win'", {
39
+ "msvs_settings": {
40
+ "VCCLCompilerTool": {
41
+ "ExceptionHandling": 1,
42
+ "AdditionalOptions": ["/std:c++17"]
43
+ }
44
+ }
45
+ }]
46
+ ]
47
+ }
48
+ ]
49
+ }
@@ -0,0 +1,395 @@
1
+ #include "http_core.h"
2
+ #include <route.h>
3
+ #include "http_scanner.h"
4
+ #include <cpool.h>
5
+
6
+ #include <string>
7
+ #include <napi.h>
8
+ #include <iostream>
9
+
10
+ __attribute__((always_inline))
11
+ void HttpCore::setMethodFlag(MethodType method) {
12
+ if (method >= M_HEAD && method <= M_OPTIONS)
13
+ this->m_methodFlags |= (1 << method);
14
+ }
15
+
16
+ __attribute__((always_inline))
17
+ bool HttpCore::isMethodAllowed(MethodType method) {
18
+ if (method <= M_HEAD || method > M_OPTIONS) return false;
19
+ return this->m_methodFlags & (1 << method);
20
+ }
21
+
22
+ static inline bool isHttp11AtOffset(const char* curl, size_t curlLen, uint32_t* offset) {
23
+ if (!offset) return false;
24
+ uint32_t pos = *offset;
25
+
26
+ static constexpr const char* pattern = "HTTP/1.1";
27
+ static constexpr size_t plen = 8;
28
+
29
+ // sınır kontrolü (out of range)
30
+ if (pos + plen > curlLen) return false;
31
+ // memcmp — char by char karşılaştırmanın en hızlı yolu
32
+ if (memcmp(curl + pos, pattern, plen) != 0) {
33
+ return false;
34
+ }
35
+
36
+ // eşleşti → offset ilerlet
37
+ *offset = pos + plen;
38
+ return true;
39
+ }
40
+
41
+ static inline MethodType scanHttpMethod(const char* curl, uint32_t* offset) {
42
+ const char* p = curl + *offset;
43
+ switch (*p) {
44
+ case 'G':
45
+ if (__builtin_expect(*(p+1) == 'E' && *(p+2) == 'T' &&
46
+ (*(p+3) == ' ' || *(p+3) == '\0'), 1)) {
47
+ *offset += 3;
48
+ return M_GET;
49
+ }
50
+ break;
51
+ case 'H':
52
+ if (__builtin_expect(*(p+1) == 'E' && *(p+2) == 'A' && *(p+3) == 'D' &&
53
+ (*(p+4) == ' ' || *(p+4) == '\0'), 1)) {
54
+ *offset += 4;
55
+ return M_HEAD;
56
+ }
57
+ break;
58
+ case 'P':
59
+ switch (*(p+1)) {
60
+ case 'O':
61
+ if (__builtin_expect(*(p+2) == 'S' && *(p+3) == 'T' &&
62
+ (*(p+4) == ' ' || *(p+4) == '\0'), 1)) {
63
+ *offset += 4;
64
+ return M_POST;
65
+ }
66
+ break;
67
+ case 'U':
68
+ if (__builtin_expect(*(p+2) == 'T' && (*(p+3) == ' ' || *(p+3) == '\0'), 1)) {
69
+ *offset += 3;
70
+ return M_PUT;
71
+ }
72
+ break;
73
+ case 'A':
74
+ if (__builtin_expect(*(p+2) == 'T' && *(p+3) == 'C' && *(p+4) == 'H' &&
75
+ (*(p+5) == ' ' || *(p+5) == '\0'), 1)) {
76
+ *offset += 5;
77
+ return M_PATCH;
78
+ }
79
+ break;
80
+ }
81
+ break;
82
+ case 'D':
83
+ if (__builtin_expect(*(p+1) == 'E' && *(p+2) == 'L' && *(p+3) == 'E' &&
84
+ *(p+4) == 'T' && *(p+5) == 'E' &&
85
+ (*(p+6) == ' ' || *(p+6) == '\0'), 0)) {
86
+ *offset += 6;
87
+ return M_DELETE;
88
+ }
89
+ break;
90
+ case 'O':
91
+ if (__builtin_expect(*(p+1) == 'P' && *(p+2) == 'T' && *(p+3) == 'I' &&
92
+ *(p+4) == 'O' && *(p+5) == 'N' && *(p+6) == 'S' &&
93
+ (*(p+7) == ' ' || *(p+7) == '\0'), 0)) {
94
+ *offset += 7;
95
+ return M_OPTIONS;
96
+ }
97
+ break;
98
+ }
99
+
100
+ return M_ERROR;
101
+ }
102
+
103
+ Napi::Function HttpCore::GetClass(Napi::Env env) {
104
+ return DefineClass(env, "HttpCore", {
105
+ InstanceMethod("registerRoutes", &HttpCore::RegisterRoutes),
106
+ InstanceMethod("scannerRouteFirst", &HttpCore::ScannerRouteFirst),
107
+ InstanceMethod("scannerHeader", &HttpCore::ScannerHeader),
108
+ InstanceMethod("printRouteTree", &HttpCore::PrintRouteTree),
109
+ });
110
+ }
111
+
112
+ HttpCore::HttpCore(const Napi::CallbackInfo& info)
113
+ : Napi::ObjectWrap<HttpCore>(info) {
114
+
115
+ }
116
+
117
+ HttpCore::~HttpCore() {
118
+
119
+ }
120
+
121
+ RouteBuilder::EndpointParam HttpCore::makeParam(const std::string& name, RouteBuilder::ParamType type) {
122
+ return RouteBuilder::EndpointParam{ name, type };
123
+ }
124
+
125
+ RouteBuilder::Endpoint HttpCore::makeEndpoint(const std::string& url, int vptr_table_index) {
126
+ RouteBuilder::Endpoint ep{};
127
+ std::string out;
128
+ std::vector<RouteBuilder::EndpointParam> params;
129
+
130
+ out.reserve(url.size());
131
+
132
+ for (size_t i = 0; i < url.size();) {
133
+ if (url[i] == ':' && (i == 0 || url[i - 1] == '/')) {
134
+ size_t start = i + 1;
135
+ size_t end = start;
136
+
137
+ while (end < url.size() && url[end] != '/' && url[end] != '?')
138
+ end++;
139
+
140
+ std::string paramName = url.substr(start, end - start);
141
+
142
+ out.push_back(':');
143
+ out += paramName;
144
+ params.push_back(makeParam(paramName, RouteBuilder::kString));
145
+ i = end;
146
+ } else {
147
+ out.push_back(url[i]);
148
+ ++i;
149
+ }
150
+ }
151
+
152
+ ep.url = strdup(out.c_str());
153
+ ep.params = std::move(params);
154
+ ep.vptr_table_index = vptr_table_index;
155
+
156
+ return ep;
157
+ }
158
+
159
+ MethodType HttpCore::parserMethod(const std::string& method) {
160
+ if (method == "HEAD") return M_HEAD;
161
+ if (method == "GET") return M_GET;
162
+ if (method == "POST") return M_POST;
163
+ if (method == "PUT") return M_PUT;
164
+ if (method == "DELETE") return M_DELETE;
165
+ if (method == "PATCH") return M_PATCH;
166
+ if (method == "OPTIONS") return M_OPTIONS;
167
+ return M_ERROR;
168
+ }
169
+
170
+ Napi::Value HttpCore::RegisterRoutes(const Napi::CallbackInfo& info) {
171
+ Napi::Env env = info.Env();
172
+
173
+ if (info.Length() < 1 || !info[0].IsArray()) {
174
+ Napi::TypeError::New(env, "Expected an array of route definitions").ThrowAsJavaScriptException();
175
+ return env.Null();
176
+ }
177
+
178
+ Napi::Array routes = info[0].As<Napi::Array>();
179
+ size_t routeCounts = routes.Length();
180
+
181
+ std::unique_ptr<std::vector<RouteBuilder::Endpoint>> methodEndpoints[METHOD_MAX_INDEX_COUNT];
182
+ for (int i = 0; i < METHOD_MAX_INDEX_COUNT; ++i) {
183
+ methodEndpoints[i] = std::make_unique<std::vector<RouteBuilder::Endpoint>>();
184
+ }
185
+
186
+ for (size_t i = 0; i < routeCounts; i++) {
187
+ Napi::Value val = routes[i];
188
+ if (!val.IsObject()) continue;
189
+
190
+ Napi::Object routeObj = val.As<Napi::Object>();
191
+
192
+ std::string method = routeObj.Get("method").ToString();
193
+ std::string url = routeObj.Get("route").ToString();
194
+ int vptr_table_index = routeObj.Get("vptrTableIndex").As<Napi::Number>().Int32Value();
195
+
196
+ MethodType indexMethod = parserMethod(method);
197
+ if (indexMethod == M_ERROR) continue;
198
+
199
+ RouteBuilder::Endpoint ep = makeEndpoint(url, vptr_table_index);
200
+
201
+ methodEndpoints[static_cast<int>(indexMethod)]->push_back(std::move(ep));
202
+ }
203
+
204
+ for (uint8_t index = 0; index < METHOD_MAX_INDEX_COUNT; ++index) {
205
+ auto& eps = methodEndpoints[index];
206
+ if (eps && !eps->empty()) {
207
+ auto routeBuilder = RouteBuilder::buildRouteTree(std::move(*eps));
208
+
209
+ // RouteBuilder::printRouteTree(routeBuilder); // For Debug
210
+
211
+ this->m_httpRouteMaps[index].route_node = routeBuilder;
212
+ setMethodFlag((MethodType)index);
213
+ }
214
+ }
215
+
216
+ return Napi::Number::New(env, routeCounts);
217
+ }
218
+
219
+ Napi::Value HttpCore::ScannerRouteFirst(const Napi::CallbackInfo& info) {
220
+ Napi::Env env = info.Env();
221
+
222
+ auto curlBuf = info[0].As<Napi::Buffer<uint8_t>>();
223
+ uint8_t* curl = curlBuf.Data();
224
+ size_t curlLen = curlBuf.Length();
225
+
226
+ Napi::Object reqObj = info[1].As<Napi::Object>();
227
+
228
+ uint32_t main_offset = 0;
229
+
230
+ // ------------- SCAN METHOD ----------------
231
+ MethodType methodType = scanHttpMethod((const char*)curl, &main_offset);
232
+
233
+ if (!isMethodAllowed(methodType)) {
234
+ if (methodType == M_ERROR) {
235
+ uint32_t flags = FLAG_BAD_REQUEST;
236
+ reqObj.Set("retFlag", Napi::Number::New(env, flags));
237
+ return Napi::Number::New(env, -1);
238
+ }
239
+
240
+ uint32_t flags = FLAG_METHOD_NOT_ALLOWED;
241
+ if (methodType == M_OPTIONS)
242
+ flags |= FLAG_CORS_PREFLIGHT;
243
+
244
+ reqObj.Set("retFlag", Napi::Number::New(env, flags));
245
+ reqObj.Set("mainOffset", Napi::Number::New(env, main_offset));
246
+ return Napi::Number::New(env, -1);
247
+ }
248
+
249
+ reqObj.Set("method", Napi::Number::New(env, (int)methodType));
250
+
251
+ main_offset += 1;
252
+
253
+ Napi::Array params = Napi::Array::New(env);
254
+ Napi::Object query = Napi::Object::New(env);
255
+
256
+ uint32_t query_limit = info[5].As<Napi::Number>();
257
+ // --------- MATCH ROUTE -------------
258
+ int routeId = RouteBuilder::matchUrl(env,
259
+ this->m_httpRouteMaps[methodType].route_node,
260
+ (const char*)curl,
261
+ curlLen,
262
+ &main_offset,
263
+ &params,
264
+ &query,
265
+ query_limit
266
+ );
267
+
268
+ if(routeId == -1) {
269
+ reqObj.Set("retFlag", Napi::Number::New(env, FLAG_NOT_FOUND));
270
+ return Napi::Number::New(env, -1);
271
+ } else if (routeId == -2) {
272
+ reqObj.Set("retFlag", Napi::Number::New(env, FLAG_REQUEST_QUERY_EXCEEDED));
273
+ return Napi::Number::New(env, -1);
274
+ } else if (routeId == -3) {
275
+ reqObj.Set("retFlag", Napi::Number::New(env, FLAG_REQUEST_URL_EXCEEDED));
276
+ return Napi::Number::New(env, -1);
277
+ }
278
+
279
+ reqObj.Set("params", params);
280
+ reqObj.Set("query", query);
281
+
282
+ main_offset += 1;
283
+ // --------- HTTP VERSION VALIDATION ---------
284
+ bool ret = isHttp11AtOffset((const char*)curl, curlLen, &main_offset);
285
+ if (!ret) {
286
+ reqObj.Set("retFlag", Napi::Number::New(env, FLAG_HTTP_VERSION_UNSUPPORTED));
287
+ return Napi::Number::New(env, routeId);
288
+ }
289
+
290
+ main_offset += 2;
291
+ // --------- HEADER SCANNER ---------
292
+ uint32_t currentHeaderSize = reqObj.Get("headerSize").As<Napi::Number>();
293
+ uint32_t maxHeaderNameSize = info[2].As<Napi::Number>();
294
+ uint32_t maxHeaderValueSize = info[3].As<Napi::Number>();
295
+ uint32_t maxHeaderSize = info[4].As<Napi::Number>();
296
+ Napi::Object headers = reqObj.Get("headers").As<Napi::Object>();
297
+ auto sOff = main_offset;
298
+ auto res = scanHeaders(env,
299
+ (const char*)curl, curlLen,
300
+ &main_offset,
301
+ maxHeaderSize,
302
+
303
+ maxHeaderSize,
304
+ maxHeaderValueSize,
305
+ currentHeaderSize,
306
+
307
+ methodType,
308
+ &headers);
309
+ reqObj.Set("retFlag", (int)res);
310
+ reqObj.Set("headerSize", Napi::Number::New(env, currentHeaderSize + main_offset - sOff));
311
+ // -------- SUCCESS -----------
312
+ reqObj.Set("mainOffset", Napi::Number::New(env, main_offset));
313
+
314
+ return Napi::Number::New(env, routeId);
315
+ }
316
+
317
+ Napi::Value HttpCore::ScannerHeader(const Napi::CallbackInfo& info) {
318
+ Napi::Env env = info.Env();
319
+
320
+ auto curlBuf = info[0].As<Napi::Buffer<uint8_t>>();
321
+ uint8_t* curl = curlBuf.Data();
322
+ size_t curlLen = curlBuf.Length();
323
+
324
+ Napi::Object reqObj = info[1].As<Napi::Object>();
325
+ uint32_t maxHeaderNameSize = info[2].As<Napi::Number>();
326
+ uint32_t maxHeaderValueSize = info[3].As<Napi::Number>();
327
+ uint32_t maxHeaderSize = info[4].As<Napi::Number>();
328
+
329
+ uint32_t mainOff = reqObj.Get("mainOffset").As<Napi::Number>();
330
+ uint32_t currentHeaderSize = reqObj.Get("headerSize").As<Napi::Number>();
331
+
332
+ Napi::Object headers = reqObj.Get("headers").As<Napi::Object>();
333
+ uint32_t methodType = reqObj.Get("method").As<Napi::Number>();
334
+ auto sOff = mainOff;
335
+ auto res = scanHeaders(env,
336
+ (const char*)curl, curlLen,
337
+ &mainOff,
338
+ maxHeaderSize,
339
+
340
+ maxHeaderNameSize,
341
+ maxHeaderValueSize,
342
+ currentHeaderSize,
343
+
344
+ (MethodType)methodType,
345
+ &headers);
346
+ reqObj.Set("retFlag", (int)res);
347
+ reqObj.Set("headerSize", Napi::Number::New(env, currentHeaderSize + mainOff - sOff));
348
+ // -------- SUCCESS -----------
349
+ reqObj.Set("mainOffset", Napi::Number::New(env, mainOff));
350
+
351
+ return Napi::Number::New(env, 0);
352
+ }
353
+
354
+ Napi::Value HttpCore::PrintRouteTree(const Napi::CallbackInfo& info) {
355
+ Napi::Env env = info.Env();
356
+
357
+ auto deepth = 4;
358
+
359
+ if (info.Length() == 1 || !info[0].IsNumber()) {
360
+ deepth = info[0].As<Napi::Number>();
361
+ }
362
+
363
+ for (auto i = 0; i < METHOD_MAX_INDEX_COUNT; i++) {
364
+ std::string methodName = "";
365
+ switch (this->m_httpRouteMaps[i].method_type) {
366
+ case M_HEAD:
367
+ methodName = "HEAD";
368
+ break;
369
+ case M_GET:
370
+ methodName = "GET";
371
+ break;
372
+ case M_POST:
373
+ methodName = "POST";
374
+ break;
375
+ case M_PUT:
376
+ methodName = "PUT";
377
+ break;
378
+ case M_PATCH:
379
+ methodName = "PATCH";
380
+ break;
381
+ case M_DELETE:
382
+ methodName = "DELETE";
383
+ break;
384
+ case M_OPTIONS:
385
+ methodName = "OPTIONS";
386
+ break;
387
+ default:
388
+ break;
389
+ }
390
+ std::cout << methodName << "\n";
391
+ RouteBuilder::printRouteTree(this->m_httpRouteMaps[i].route_node, deepth);
392
+ }
393
+
394
+ return Napi::Number::New(env, 0);
395
+ }
@@ -0,0 +1,90 @@
1
+ #pragma once
2
+ #include <napi.h>
3
+ #include <route.h>
4
+ #include <string>
5
+
6
+ using namespace std;
7
+
8
+ constexpr uint8_t METHOD_MAX_INDEX_COUNT = 7;
9
+
10
+ enum FlagBits : uint32_t {
11
+ FLAG_OK = 0x0000,
12
+ FLAG_BAD_REQUEST = 0x0001,
13
+ FLAG_METHOD_NOT_ALLOWED = 0x0002,
14
+ FLAG_NOT_FOUND = 0x0004,
15
+ FLAG_CORS_PREFLIGHT = 0x0008,
16
+ FLAG_HTTP_VERSION_UNSUPPORTED = 0x0010,
17
+ FLAG_CONTENT_LENGTH_TOO_LARGE = 0x0020,
18
+ FLAG_MISSING_HOST = 0x0040,
19
+ FLAG_HAS_BODY = 0x0080,
20
+ FLAG_INVALID_ARGUMENT = 0x0100,
21
+ FLAG_INVALID_HEADER = 0x0200,
22
+ FLAG_INVALID_HEADER_VALUE = 0X0300,
23
+ FLAG_INVALID_CONTENT_LENGTH = 0x0400,
24
+ FLAG_CONTENT_LENGTH_EXCEEDED = 0x0800,
25
+ FLAG_UNTERMINATED_HEADERS = 0x1000,
26
+ FLAG_MAX_HEADER_SIZE = 0X2000,
27
+ FLAG_MAX_HEADER_NAME_SIZE = 0X2100,
28
+ FLAG_MAX_HEADER_VALUE_SIZE = 0X2200,
29
+ FLAG_DUPLICATE_SINGLE_HEADER = 0X3000,
30
+ FLAG_REQUEST_QUERY_EXCEEDED = 0X4000,
31
+ FLAG_REQUEST_URL_EXCEEDED = 0X5000,
32
+ FLAG_SMUGGING_TE_CL = 0x6000
33
+ };
34
+
35
+ using MethodFlags = uint8_t;
36
+
37
+ enum MethodType : uint8_t {
38
+ M_HEAD,
39
+ M_GET,
40
+ M_POST,
41
+ M_PUT,
42
+ M_DELETE,
43
+ M_PATCH,
44
+ M_OPTIONS,
45
+ M_ERROR,
46
+ };
47
+
48
+ enum HttpContextMode: uint8_t {
49
+ M_WEB,
50
+ M_API
51
+ };
52
+
53
+ struct HttpRoutes {
54
+ MethodType method_type;
55
+ shared_ptr<RouteBuilder::RouteNode> route_node; // Builded Route Node
56
+ };
57
+
58
+ class HttpCore : public Napi::ObjectWrap<HttpCore> {
59
+ public:
60
+ static Napi::Function GetClass(Napi::Env env);
61
+ HttpCore(const Napi::CallbackInfo& info);
62
+ ~HttpCore();
63
+
64
+ // NAPI methods
65
+ Napi::Value RegisterRoutes(const Napi::CallbackInfo& info);
66
+ Napi::Value ScannerRouteFirst(const Napi::CallbackInfo& info);
67
+ Napi::Value ScannerHeader(const Napi::CallbackInfo& info);
68
+ Napi::Value PrintRouteTree(const Napi::CallbackInfo& info);
69
+
70
+ private:
71
+ HttpContextMode m_httpContextMode;
72
+ MethodFlags m_methodFlags = 0;
73
+ HttpRoutes m_httpRouteMaps[METHOD_MAX_INDEX_COUNT] = {
74
+ { M_HEAD, nullptr },
75
+ { M_GET, nullptr },
76
+ { M_POST, nullptr },
77
+ { M_PUT, nullptr },
78
+ { M_DELETE, nullptr },
79
+ { M_PATCH, nullptr },
80
+ { M_OPTIONS, nullptr },
81
+ };
82
+
83
+ // helpers
84
+ MethodType parserMethod(const std::string& method);
85
+ void setMethodFlag(MethodType method);
86
+ bool isMethodAllowed(MethodType method);
87
+
88
+ RouteBuilder::Endpoint makeEndpoint(const std::string& url, int vptr_table_index);
89
+ RouteBuilder::EndpointParam makeParam(const std::string& name, RouteBuilder::ParamType type);
90
+ };