@e22m4u/js-trie-router 0.7.6 → 0.7.7

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/build-cjs.js CHANGED
@@ -6,7 +6,7 @@ await esbuild.build({
6
6
  outfile: 'dist/cjs/index.cjs',
7
7
  format: 'cjs',
8
8
  platform: 'node',
9
- target: ['node16'],
9
+ target: ['node18'],
10
10
  bundle: true,
11
11
  keepNames: true,
12
12
  external: [
@@ -86,7 +86,10 @@ var import_js_debug = require("@e22m4u/js-debug");
86
86
  // src/debuggable-service.js
87
87
  var import_js_service = require("@e22m4u/js-service");
88
88
  var MODULE_DEBUG_NAMESPACE = "jsTrieRouter";
89
- var _DebuggableService = class _DebuggableService extends import_js_service.DebuggableService {
89
+ var DebuggableService = class extends import_js_service.DebuggableService {
90
+ static {
91
+ __name(this, "DebuggableService");
92
+ }
90
93
  /**
91
94
  * Constructor.
92
95
  *
@@ -99,8 +102,6 @@ var _DebuggableService = class _DebuggableService extends import_js_service.Debu
99
102
  });
100
103
  }
101
104
  };
102
- __name(_DebuggableService, "DebuggableService");
103
- var DebuggableService = _DebuggableService;
104
105
 
105
106
  // src/utils/clone-deep.js
106
107
  function cloneDeep(value) {
@@ -953,7 +954,10 @@ __name(getRequestPathname, "getRequestPathname");
953
954
  // src/request-context.js
954
955
  var import_js_format11 = require("@e22m4u/js-format");
955
956
  var import_js_service2 = require("@e22m4u/js-service");
956
- var _RequestContext = class _RequestContext {
957
+ var RequestContext = class {
958
+ static {
959
+ __name(this, "RequestContext");
960
+ }
957
961
  /**
958
962
  * Service container.
959
963
  *
@@ -1139,8 +1143,6 @@ var _RequestContext = class _RequestContext {
1139
1143
  this._route = route;
1140
1144
  }
1141
1145
  };
1142
- __name(_RequestContext, "RequestContext");
1143
- var RequestContext = _RequestContext;
1144
1146
 
1145
1147
  // src/hooks/router-hook-invoker.js
1146
1148
  var import_js_format13 = require("@e22m4u/js-format");
@@ -1154,7 +1156,10 @@ var RouterHookType = {
1154
1156
  POST_HANDLER: "postHandler"
1155
1157
  };
1156
1158
  var ROUTER_HOOK_TYPES = Object.values(RouterHookType);
1157
- var _RouterHookRegistry = class _RouterHookRegistry {
1159
+ var RouterHookRegistry = class {
1160
+ static {
1161
+ __name(this, "RouterHookRegistry");
1162
+ }
1158
1163
  /**
1159
1164
  * Hooks.
1160
1165
  *
@@ -1237,11 +1242,12 @@ var _RouterHookRegistry = class _RouterHookRegistry {
1237
1242
  return this._hooks.get(type) || [];
1238
1243
  }
1239
1244
  };
1240
- __name(_RouterHookRegistry, "RouterHookRegistry");
1241
- var RouterHookRegistry = _RouterHookRegistry;
1242
1245
 
1243
1246
  // src/hooks/router-hook-invoker.js
1244
- var _RouterHookInvoker = class _RouterHookInvoker extends DebuggableService {
1247
+ var RouterHookInvoker = class extends DebuggableService {
1248
+ static {
1249
+ __name(this, "RouterHookInvoker");
1250
+ }
1245
1251
  /**
1246
1252
  * Invoke on-request hooks.
1247
1253
  *
@@ -1502,8 +1508,6 @@ var _RouterHookInvoker = class _RouterHookInvoker extends DebuggableService {
1502
1508
  return currentData;
1503
1509
  }
1504
1510
  };
1505
- __name(_RouterHookInvoker, "RouterHookInvoker");
1506
- var RouterHookInvoker = _RouterHookInvoker;
1507
1511
 
1508
1512
  // src/route/validate-route-definition.js
1509
1513
  var import_js_format14 = require("@e22m4u/js-format");
@@ -1586,6 +1590,7 @@ __name(validateRouteDefinition, "validateRouteDefinition");
1586
1590
  // src/route/route.js
1587
1591
  var HttpMethod = {
1588
1592
  GET: "GET",
1593
+ HEAD: "HEAD",
1589
1594
  POST: "POST",
1590
1595
  PUT: "PUT",
1591
1596
  PATCH: "PATCH",
@@ -1593,7 +1598,10 @@ var HttpMethod = {
1593
1598
  OPTIONS: "OPTIONS"
1594
1599
  };
1595
1600
  var DEFAULT_META = Object.freeze({});
1596
- var _Route = class _Route extends import_js_debug.Debuggable {
1601
+ var Route = class extends import_js_debug.Debuggable {
1602
+ static {
1603
+ __name(this, "Route");
1604
+ }
1597
1605
  /**
1598
1606
  * Definition.
1599
1607
  *
@@ -1695,14 +1703,15 @@ var _Route = class _Route extends import_js_debug.Debuggable {
1695
1703
  return this.handler(context);
1696
1704
  }
1697
1705
  };
1698
- __name(_Route, "Route");
1699
- var Route = _Route;
1700
1706
 
1701
1707
  // src/route/route-registry.js
1702
1708
  var import_js_path_trie = require("@e22m4u/js-path-trie");
1703
1709
  var import_js_service3 = require("@e22m4u/js-service");
1704
1710
  var import_js_format15 = require("@e22m4u/js-format");
1705
- var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1711
+ var RouteRegistry = class extends DebuggableService {
1712
+ static {
1713
+ __name(this, "RouteRegistry");
1714
+ }
1706
1715
  /**
1707
1716
  * Constructor.
1708
1717
  *
@@ -1792,38 +1801,7 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1792
1801
  requestPath
1793
1802
  );
1794
1803
  }
1795
- /**
1796
- * Get allowed methods for request path.
1797
- *
1798
- * @param {string} requestPath
1799
- * @returns {string[]}
1800
- */
1801
- getAllowedMethodsForRequestPath(requestPath) {
1802
- if (typeof requestPath !== "string") {
1803
- throw new import_js_format15.InvalidArgumentError(
1804
- 'Parameter "requestPath" must be a String, but %v was given.',
1805
- requestPath
1806
- );
1807
- }
1808
- const debug = this.getDebuggerFor(this.getAllowedMethodsForRequestPath);
1809
- const allowedMethods = [];
1810
- for (const method of Object.values(HttpMethod)) {
1811
- const rawTriePath = `${method}/${requestPath}`;
1812
- const triePath = rawTriePath.replace(/\/+/g, "/");
1813
- if (this._trie.match(triePath)) {
1814
- allowedMethods.push(method);
1815
- }
1816
- }
1817
- if (allowedMethods.length) {
1818
- debug("Allowed methods for %v are: %l.", requestPath, allowedMethods);
1819
- } else {
1820
- debug("Path %v does not have allowed methods.", requestPath);
1821
- }
1822
- return allowedMethods;
1823
- }
1824
1804
  };
1825
- __name(_RouteRegistry, "RouteRegistry");
1826
- var RouteRegistry = _RouteRegistry;
1827
1805
 
1828
1806
  // src/branch/router-branch.js
1829
1807
  var import_js_format17 = require("@e22m4u/js-format");
@@ -1934,7 +1912,10 @@ function mergeRouterBranchDefinitions(firstDef, secondDef) {
1934
1912
  __name(mergeRouterBranchDefinitions, "mergeRouterBranchDefinitions");
1935
1913
 
1936
1914
  // src/branch/router-branch.js
1937
- var _RouterBranch = class _RouterBranch extends DebuggableService {
1915
+ var RouterBranch = class _RouterBranch extends DebuggableService {
1916
+ static {
1917
+ __name(this, "RouterBranch");
1918
+ }
1938
1919
  /**
1939
1920
  * Router.
1940
1921
  *
@@ -2053,8 +2034,6 @@ var _RouterBranch = class _RouterBranch extends DebuggableService {
2053
2034
  return new _RouterBranch(this._router, branchDef, this);
2054
2035
  }
2055
2036
  };
2056
- __name(_RouterBranch, "RouterBranch");
2057
- var RouterBranch = _RouterBranch;
2058
2037
 
2059
2038
  // src/parsers/request-parser.js
2060
2039
  var import_http3 = require("http");
@@ -2066,7 +2045,10 @@ var import_js_format19 = require("@e22m4u/js-format");
2066
2045
 
2067
2046
  // src/trie-router-options.js
2068
2047
  var import_js_format18 = require("@e22m4u/js-format");
2069
- var _TrieRouterOptions = class _TrieRouterOptions {
2048
+ var TrieRouterOptions = class {
2049
+ static {
2050
+ __name(this, "TrieRouterOptions");
2051
+ }
2070
2052
  /**
2071
2053
  * Request body bytes limit.
2072
2054
  *
@@ -2141,11 +2123,12 @@ var _TrieRouterOptions = class _TrieRouterOptions {
2141
2123
  }
2142
2124
  }
2143
2125
  };
2144
- __name(_TrieRouterOptions, "TrieRouterOptions");
2145
- var TrieRouterOptions = _TrieRouterOptions;
2146
2126
 
2147
2127
  // src/parsers/request-body-parser.js
2148
- var _RequestBodyParser = class _RequestBodyParser extends DebuggableService {
2128
+ var RequestBodyParser = class extends DebuggableService {
2129
+ static {
2130
+ __name(this, "RequestBodyParser");
2131
+ }
2149
2132
  /**
2150
2133
  * Parsers.
2151
2134
  *
@@ -2288,8 +2271,6 @@ var _RequestBodyParser = class _RequestBodyParser extends DebuggableService {
2288
2271
  });
2289
2272
  }
2290
2273
  };
2291
- __name(_RequestBodyParser, "RequestBodyParser");
2292
- var RequestBodyParser = _RequestBodyParser;
2293
2274
  function parseJsonBody(input) {
2294
2275
  if (typeof input !== "string") {
2295
2276
  return void 0;
@@ -2304,7 +2285,10 @@ __name(parseJsonBody, "parseJsonBody");
2304
2285
 
2305
2286
  // src/parsers/request-query-parser.js
2306
2287
  var import_querystring2 = __toESM(require("querystring"), 1);
2307
- var _RequestQueryParser = class _RequestQueryParser extends DebuggableService {
2288
+ var RequestQueryParser = class extends DebuggableService {
2289
+ static {
2290
+ __name(this, "RequestQueryParser");
2291
+ }
2308
2292
  /**
2309
2293
  * Parse
2310
2294
  *
@@ -2330,11 +2314,12 @@ var _RequestQueryParser = class _RequestQueryParser extends DebuggableService {
2330
2314
  return query;
2331
2315
  }
2332
2316
  };
2333
- __name(_RequestQueryParser, "RequestQueryParser");
2334
- var RequestQueryParser = _RequestQueryParser;
2335
2317
 
2336
2318
  // src/parsers/request-cookies-parser.js
2337
- var _RequestCookiesParser = class _RequestCookiesParser extends DebuggableService {
2319
+ var RequestCookiesParser = class extends DebuggableService {
2320
+ static {
2321
+ __name(this, "RequestCookiesParser");
2322
+ }
2338
2323
  /**
2339
2324
  * Parse
2340
2325
  *
@@ -2360,11 +2345,12 @@ var _RequestCookiesParser = class _RequestCookiesParser extends DebuggableServic
2360
2345
  return cookies;
2361
2346
  }
2362
2347
  };
2363
- __name(_RequestCookiesParser, "RequestCookiesParser");
2364
- var RequestCookiesParser = _RequestCookiesParser;
2365
2348
 
2366
2349
  // src/parsers/request-parser.js
2367
- var _RequestParser = class _RequestParser extends DebuggableService {
2350
+ var RequestParser = class extends DebuggableService {
2351
+ static {
2352
+ __name(this, "RequestParser");
2353
+ }
2368
2354
  /**
2369
2355
  * Parse.
2370
2356
  *
@@ -2402,15 +2388,16 @@ var _RequestParser = class _RequestParser extends DebuggableService {
2402
2388
  return promises.length ? Promise.all(promises).then(() => data) : data;
2403
2389
  }
2404
2390
  };
2405
- __name(_RequestParser, "RequestParser");
2406
- var RequestParser = _RequestParser;
2407
2391
 
2408
2392
  // src/trie-router.js
2409
2393
  var import_http4 = require("http");
2410
2394
 
2411
2395
  // src/senders/router-data-sender.js
2412
2396
  var import_js_format21 = require("@e22m4u/js-format");
2413
- var _RouterDataSender = class _RouterDataSender extends DebuggableService {
2397
+ var RouterDataSender = class extends DebuggableService {
2398
+ static {
2399
+ __name(this, "RouterDataSender");
2400
+ }
2414
2401
  /**
2415
2402
  * Send.
2416
2403
  *
@@ -2471,14 +2458,15 @@ var _RouterDataSender = class _RouterDataSender extends DebuggableService {
2471
2458
  debug(debugMsg);
2472
2459
  }
2473
2460
  };
2474
- __name(_RouterDataSender, "RouterDataSender");
2475
- var RouterDataSender = _RouterDataSender;
2476
2461
 
2477
2462
  // src/senders/router-error-sender.js
2478
2463
  var import_util = require("util");
2479
2464
  var import_statuses = __toESM(require("statuses"), 1);
2480
2465
  var EXPOSED_ERROR_PROPERTIES = ["code", "details"];
2481
- var _RouterErrorSender = class _RouterErrorSender extends DebuggableService {
2466
+ var RouterErrorSender = class extends DebuggableService {
2467
+ static {
2468
+ __name(this, "RouterErrorSender");
2469
+ }
2482
2470
  /**
2483
2471
  * Handle.
2484
2472
  *
@@ -2556,12 +2544,13 @@ var _RouterErrorSender = class _RouterErrorSender extends DebuggableService {
2556
2544
  );
2557
2545
  }
2558
2546
  };
2559
- __name(_RouterErrorSender, "RouterErrorSender");
2560
- var RouterErrorSender = _RouterErrorSender;
2561
2547
 
2562
2548
  // src/trie-router.js
2563
2549
  var import_js_service4 = require("@e22m4u/js-service");
2564
- var _TrieRouter = class _TrieRouter extends DebuggableService {
2550
+ var TrieRouter = class extends DebuggableService {
2551
+ static {
2552
+ __name(this, "TrieRouter");
2553
+ }
2565
2554
  /**
2566
2555
  * Constructor.
2567
2556
  *
@@ -2616,7 +2605,7 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
2616
2605
  * Example:
2617
2606
  * ```js
2618
2607
  * const router = new TrieRouter();
2619
- * const apiBranch = router.createBranch({path: 'api'});
2608
+ * const apiBranch = router.createBranch({path: '/api'});
2620
2609
  *
2621
2610
  * // GET /api/hello
2622
2611
  * apiBranch.defineRoute({
@@ -2683,22 +2672,6 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
2683
2672
  }
2684
2673
  const resolved = this.getService(RouteRegistry).matchRouteByRequest(request);
2685
2674
  if (!resolved) {
2686
- if (request.method.toUpperCase() === HttpMethod.OPTIONS) {
2687
- const allowedMethods = this.getService(RouteRegistry).getAllowedMethodsForRequestPath(
2688
- requestPath
2689
- );
2690
- if (allowedMethods.length > 0) {
2691
- debug("Auto-handling OPTIONS request.");
2692
- if (!allowedMethods.includes("OPTIONS")) {
2693
- allowedMethods.push("OPTIONS");
2694
- }
2695
- const allowHeader = allowedMethods.join(", ");
2696
- response.statusCode = 204;
2697
- response.setHeader("Allow", allowHeader);
2698
- response.end();
2699
- return;
2700
- }
2701
- }
2702
2675
  debug(
2703
2676
  "No route found for the request %s %v.",
2704
2677
  request.method,
@@ -2784,8 +2757,6 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
2784
2757
  return this.getService(RouterHookRegistry).hasHook(type, hook);
2785
2758
  }
2786
2759
  };
2787
- __name(_TrieRouter, "TrieRouter");
2788
- var TrieRouter = _TrieRouter;
2789
2760
  // Annotate the CommonJS export names for ESM import in node:
2790
2761
  0 && (module.exports = {
2791
2762
  CHARACTER_ENCODING_LIST,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-trie-router",
3
- "version": "0.7.6",
3
+ "version": "0.7.7",
4
4
  "description": "HTTP маршрутизатор для Node.js на основе префиксного дерева",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -26,7 +26,7 @@
26
26
  "require": "./dist/cjs/index.cjs"
27
27
  },
28
28
  "engines": {
29
- "node": ">=16"
29
+ "node": ">=18"
30
30
  },
31
31
  "scripts": {
32
32
  "lint": "tsc && eslint ./src",
@@ -41,19 +41,19 @@
41
41
  "@e22m4u/js-debug": "~0.4.1",
42
42
  "@e22m4u/js-format": "~0.4.0",
43
43
  "@e22m4u/js-path-trie": "~0.2.0",
44
- "@e22m4u/js-service": "~0.5.1",
44
+ "@e22m4u/js-service": "~0.6.1",
45
45
  "debug": "~4.4.3",
46
46
  "http-errors": "~2.0.1",
47
47
  "statuses": "~2.0.2"
48
48
  },
49
49
  "devDependencies": {
50
- "@commitlint/cli": "~20.4.2",
51
- "@commitlint/config-conventional": "~20.4.2",
50
+ "@commitlint/cli": "~20.4.3",
51
+ "@commitlint/config-conventional": "~20.4.3",
52
52
  "@eslint/js": "~9.39.2",
53
53
  "@types/chai": "~5.2.3",
54
54
  "@types/chai-as-promised": "~8.0.2",
55
55
  "@types/mocha": "~10.0.10",
56
- "c8": "~10.1.3",
56
+ "c8": "~11.0.0",
57
57
  "chai": "~6.2.2",
58
58
  "chai-as-promised": "~8.0.2",
59
59
  "esbuild": "~0.27.3",
@@ -61,9 +61,9 @@
61
61
  "eslint-config-prettier": "~10.1.8",
62
62
  "eslint-plugin-chai-expect": "~3.1.0",
63
63
  "eslint-plugin-import": "~2.32.0",
64
- "eslint-plugin-jsdoc": "~62.7.0",
64
+ "eslint-plugin-jsdoc": "~62.7.1",
65
65
  "eslint-plugin-mocha": "~11.2.0",
66
- "globals": "~17.3.0",
66
+ "globals": "~17.4.0",
67
67
  "husky": "~9.1.7",
68
68
  "mocha": "~11.7.5",
69
69
  "prettier": "~3.8.1",
@@ -36,11 +36,4 @@ export declare class RouteRegistry extends DebuggableService {
36
36
  * @param request
37
37
  */
38
38
  matchRouteByRequest(request: IncomingMessage): ResolvedRoute | undefined;
39
-
40
- /**
41
- * Get allowed methods for request path.
42
- *
43
- * @param requestPath
44
- */
45
- getAllowedMethodsForRequestPath(requestPath: string): string[];
46
39
  }
@@ -1,4 +1,4 @@
1
- import {HttpMethod, Route} from './route.js';
1
+ import {Route} from './route.js';
2
2
  import {PathTrie} from '@e22m4u/js-path-trie';
3
3
  import {ServiceContainer} from '@e22m4u/js-service';
4
4
  import {getRequestPathname} from '../utils/index.js';
@@ -124,34 +124,4 @@ export class RouteRegistry extends DebuggableService {
124
124
  requestPath,
125
125
  );
126
126
  }
127
-
128
- /**
129
- * Get allowed methods for request path.
130
- *
131
- * @param {string} requestPath
132
- * @returns {string[]}
133
- */
134
- getAllowedMethodsForRequestPath(requestPath) {
135
- if (typeof requestPath !== 'string') {
136
- throw new InvalidArgumentError(
137
- 'Parameter "requestPath" must be a String, but %v was given.',
138
- requestPath,
139
- );
140
- }
141
- const debug = this.getDebuggerFor(this.getAllowedMethodsForRequestPath);
142
- const allowedMethods = [];
143
- for (const method of Object.values(HttpMethod)) {
144
- const rawTriePath = `${method}/${requestPath}`;
145
- const triePath = rawTriePath.replace(/\/+/g, '/');
146
- if (this._trie.match(triePath)) {
147
- allowedMethods.push(method);
148
- }
149
- }
150
- if (allowedMethods.length) {
151
- debug('Allowed methods for %v are: %l.', requestPath, allowedMethods);
152
- } else {
153
- debug('Path %v does not have allowed methods.', requestPath);
154
- }
155
- return allowedMethods;
156
- }
157
127
  }
@@ -2,7 +2,6 @@ import {expect} from 'chai';
2
2
  import {format} from '@e22m4u/js-format';
3
3
  import {Route, HttpMethod} from './route.js';
4
4
  import {RouteRegistry} from './route-registry.js';
5
- import {ServiceContainer} from '@e22m4u/js-service';
6
5
  import {RouterHookRegistry, RouterHookType} from '../hooks/index.js';
7
6
 
8
7
  describe('RouteRegistry', function () {
@@ -153,95 +152,4 @@ describe('RouteRegistry', function () {
153
152
  expect(res.params).to.be.eql({p1: 'baz', p2: 'qux'});
154
153
  });
155
154
  });
156
-
157
- describe('getAllowedMethodsForRequestPath', function () {
158
- it('should require the parameter "requestPath" to be a String', function () {
159
- const S = new RouteRegistry();
160
- const throwable = v => () => S.getAllowedMethodsForRequestPath(v);
161
- const error = v =>
162
- format(
163
- 'Parameter "requestPath" must be a String, but %s was given.',
164
- v,
165
- );
166
- expect(throwable(10)).to.throw(error('10'));
167
- expect(throwable(0)).to.throw(error('0'));
168
- expect(throwable(true)).to.throw(error('true'));
169
- expect(throwable(false)).to.throw(error('false'));
170
- expect(throwable([])).to.throw(error('Array'));
171
- expect(throwable({})).to.throw(error('Object'));
172
- expect(throwable(undefined)).to.throw(error('undefined'));
173
- expect(throwable(null)).to.throw(error('null'));
174
- expect(throwable(() => undefined)).to.throw(error('Function'));
175
- throwable('str')();
176
- throwable('')();
177
- });
178
-
179
- it('should return an empty array if no routes match the path', function () {
180
- const S = new RouteRegistry(new ServiceContainer());
181
- S.defineRoute({
182
- method: HttpMethod.GET,
183
- path: '/foo',
184
- handler: () => undefined,
185
- });
186
- const res = S.getAllowedMethodsForRequestPath('/bar');
187
- expect(res).to.be.eql([]);
188
- });
189
-
190
- it('should return an array with a single method if only one matches', function () {
191
- const S = new RouteRegistry(new ServiceContainer());
192
- S.defineRoute({
193
- method: HttpMethod.POST,
194
- path: '/foo',
195
- handler: () => undefined,
196
- });
197
- const res = S.getAllowedMethodsForRequestPath('/foo');
198
- expect(res).to.be.eql([HttpMethod.POST]);
199
- });
200
-
201
- it('should return an array with multiple methods if several routes match the path', function () {
202
- const S = new RouteRegistry(new ServiceContainer());
203
- const handler = () => undefined;
204
- S.defineRoute({method: HttpMethod.GET, path: '/foo', handler});
205
- S.defineRoute({method: HttpMethod.POST, path: '/foo', handler});
206
- S.defineRoute({method: HttpMethod.DELETE, path: '/foo', handler});
207
- const res = S.getAllowedMethodsForRequestPath('/foo');
208
- expect(res).to.be.eql([
209
- HttpMethod.GET,
210
- HttpMethod.POST,
211
- HttpMethod.DELETE,
212
- ]);
213
- });
214
-
215
- it('should correctly resolve allowed methods for paths with parameters', function () {
216
- const S = new RouteRegistry(new ServiceContainer());
217
- const handler = () => undefined;
218
- S.defineRoute({method: HttpMethod.GET, path: '/users/:id', handler});
219
- S.defineRoute({method: HttpMethod.PUT, path: '/users/:id', handler});
220
- S.defineRoute({method: HttpMethod.POST, path: '/users', handler});
221
- const res = S.getAllowedMethodsForRequestPath('/users/123');
222
- expect(res).to.be.eql([HttpMethod.GET, HttpMethod.PUT]);
223
- });
224
-
225
- it('should distinguish between paths with and without trailing slash', function () {
226
- const S = new RouteRegistry(new ServiceContainer());
227
- const handler = () => undefined;
228
- S.defineRoute({method: HttpMethod.GET, path: '/foo', handler});
229
- S.defineRoute({method: HttpMethod.POST, path: '/foo/', handler});
230
- const res1 = S.getAllowedMethodsForRequestPath('/foo');
231
- expect(res1).to.be.eql([HttpMethod.GET]);
232
- const res2 = S.getAllowedMethodsForRequestPath('/foo/');
233
- expect(res2).to.be.eql([HttpMethod.POST]);
234
- });
235
-
236
- it('should check for the explicitly defined OPTIONS method', function () {
237
- const S = new RouteRegistry(new ServiceContainer());
238
- S.defineRoute({
239
- method: HttpMethod.OPTIONS,
240
- path: '/api',
241
- handler: () => undefined,
242
- });
243
- const res = S.getAllowedMethodsForRequestPath('/api');
244
- expect(res).to.be.eql([HttpMethod.OPTIONS]);
245
- });
246
- });
247
155
  });
@@ -7,6 +7,7 @@ import {RouterHookRegistry} from '../hooks/index.js';
7
7
  */
8
8
  export declare const HttpMethod: {
9
9
  GET: 'GET';
10
+ HEAD: 'HEAD';
10
11
  POST: 'POST';
11
12
  PUT: 'PUT';
12
13
  PATCH: 'PATCH';
@@ -24,6 +24,7 @@ import {validateRouteDefinition} from './validate-route-definition.js';
24
24
  *
25
25
  * @type {{
26
26
  * GET: 'GET',
27
+ * HEAD: 'HEAD',
27
28
  * POST: 'POST',
28
29
  * PUT: 'PUT',
29
30
  * PATCH: 'PATCH',
@@ -33,6 +34,7 @@ import {validateRouteDefinition} from './validate-route-definition.js';
33
34
  */
34
35
  export const HttpMethod = {
35
36
  GET: 'GET',
37
+ HEAD: 'HEAD',
36
38
  POST: 'POST',
37
39
  PUT: 'PUT',
38
40
  PATCH: 'PATCH',
@@ -1,10 +1,10 @@
1
1
  import {RouterBranch} from './branch/index.js';
2
+ import {RouteRegistry} from './route/index.js';
2
3
  import {RequestParser} from './parsers/index.js';
3
4
  import {RequestContext} from './request-context.js';
4
5
  import {ServerResponse, IncomingMessage} from 'http';
5
6
  import {DebuggableService} from './debuggable-service.js';
6
7
  import {TrieRouterOptions} from './trie-router-options.js';
7
- import {HttpMethod, RouteRegistry} from './route/index.js';
8
8
  import {RouterDataSender, RouterErrorSender} from './senders/index.js';
9
9
  import {isServiceContainer, ServiceContainer} from '@e22m4u/js-service';
10
10
  import {isPromise, isResponseSent, getRequestPathname} from './utils/index.js';
@@ -83,7 +83,7 @@ export class TrieRouter extends DebuggableService {
83
83
  * Example:
84
84
  * ```js
85
85
  * const router = new TrieRouter();
86
- * const apiBranch = router.createBranch({path: 'api'});
86
+ * const apiBranch = router.createBranch({path: '/api'});
87
87
  *
88
88
  * // GET /api/hello
89
89
  * apiBranch.defineRoute({
@@ -165,27 +165,6 @@ export class TrieRouter extends DebuggableService {
165
165
  const resolved =
166
166
  this.getService(RouteRegistry).matchRouteByRequest(request);
167
167
  if (!resolved) {
168
- // обработка метода OPTIONS выполняется автоматически
169
- // перед отправкой ошибки 404, если для пути запроса
170
- // имеются другие методы, то вместо ошибки 404 будет
171
- // отправлен ответ с "Allow*" заголовками
172
- if (request.method.toUpperCase() === HttpMethod.OPTIONS) {
173
- const allowedMethods =
174
- this.getService(RouteRegistry).getAllowedMethodsForRequestPath(
175
- requestPath,
176
- );
177
- if (allowedMethods.length > 0) {
178
- debug('Auto-handling OPTIONS request.');
179
- if (!allowedMethods.includes('OPTIONS')) {
180
- allowedMethods.push('OPTIONS');
181
- }
182
- const allowHeader = allowedMethods.join(', ');
183
- response.statusCode = 204;
184
- response.setHeader('Allow', allowHeader);
185
- response.end();
186
- return;
187
- }
188
- }
189
168
  debug(
190
169
  'No route found for the request %s %v.',
191
170
  request.method,
@@ -1625,64 +1625,6 @@ describe('TrieRouter', function () {
1625
1625
  });
1626
1626
  });
1627
1627
  });
1628
-
1629
- describe('OPTIONS method handling', function () {
1630
- it('should automatically return 204 with specific headers for an unhandled OPTIONS request', async function () {
1631
- const router = new TrieRouter();
1632
- router.defineRoute({
1633
- method: HttpMethod.GET,
1634
- path: '/api/resource',
1635
- handler: () => 'OK',
1636
- });
1637
- router.defineRoute({
1638
- method: HttpMethod.POST,
1639
- path: '/api/resource',
1640
- handler: () => 'OK',
1641
- });
1642
- const req = createRequestMock({
1643
- method: HttpMethod.OPTIONS,
1644
- path: '/api/resource',
1645
- });
1646
- const res = createResponseMock();
1647
- await router.handleRequest(req, res);
1648
- expect(res.statusCode).to.be.eq(204);
1649
- expect(res.getHeader('Allow')).to.be.eq('GET, POST, OPTIONS');
1650
- });
1651
-
1652
- it('should execute a custom OPTIONS handler when it is explicitly defined', async function () {
1653
- const router = new TrieRouter();
1654
- let customOptionsCalled = false;
1655
- router.defineRoute({
1656
- method: HttpMethod.OPTIONS,
1657
- path: '/api/resource',
1658
- handler: () => {
1659
- customOptionsCalled = true;
1660
- return 'Custom OPTIONS response';
1661
- },
1662
- });
1663
- const req = createRequestMock({
1664
- method: HttpMethod.OPTIONS,
1665
- path: '/api/resource',
1666
- });
1667
- const res = createResponseMock();
1668
- await router.handleRequest(req, res);
1669
- const body = await res.getBody();
1670
- expect(customOptionsCalled).to.be.true;
1671
- expect(res.statusCode).to.be.eq(200);
1672
- expect(body).to.be.eq('Custom OPTIONS response');
1673
- });
1674
-
1675
- it('should return 404 for an OPTIONS request if the path does not exist for any method', async function () {
1676
- const router = new TrieRouter();
1677
- const req = createRequestMock({
1678
- method: HttpMethod.OPTIONS,
1679
- path: '/unknown',
1680
- });
1681
- const res = createResponseMock();
1682
- await router.handleRequest(req, res);
1683
- expect(res.statusCode).to.be.eq(404);
1684
- });
1685
- });
1686
1628
  });
1687
1629
 
1688
1630
  describe('addHook', function () {