@middy/http-router 6.1.6 → 6.2.0

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.
Files changed (3) hide show
  1. package/index.d.ts +44 -43
  2. package/index.js +137 -133
  3. package/package.json +69 -72
package/index.d.ts CHANGED
@@ -1,53 +1,54 @@
1
- import middy, { MiddyfiedHandler } from '@middy/core'
2
- import {
3
- ALBEvent,
4
- ALBResult,
5
- APIGatewayProxyEvent,
6
- APIGatewayProxyEventV2,
7
- APIGatewayProxyResult,
8
- APIGatewayProxyResultV2,
9
- Handler as LambdaHandler
10
- } from 'aws-lambda'
1
+ import type middy from "@middy/core";
2
+ import type { MiddyfiedHandler } from "@middy/core";
3
+ import type {
4
+ ALBEvent,
5
+ ALBResult,
6
+ APIGatewayProxyEvent,
7
+ APIGatewayProxyEventV2,
8
+ APIGatewayProxyResult,
9
+ APIGatewayProxyResultV2,
10
+ Handler as LambdaHandler,
11
+ } from "aws-lambda";
11
12
 
12
13
  export type Method =
13
- | 'GET'
14
- | 'POST'
15
- | 'PUT'
16
- | 'PATCH'
17
- | 'DELETE'
18
- | 'OPTIONS'
19
- | 'HEAD'
20
- | 'ANY'
14
+ | "GET"
15
+ | "POST"
16
+ | "PUT"
17
+ | "PATCH"
18
+ | "DELETE"
19
+ | "OPTIONS"
20
+ | "HEAD"
21
+ | "ANY";
21
22
 
22
23
  export interface Route<TEvent, TResult> {
23
- method: Method
24
- path: string
25
- handler:
26
- | LambdaHandler<TEvent, TResult>
27
- | MiddyfiedHandler<TEvent, TResult, any, any>
24
+ method: Method;
25
+ path: string;
26
+ handler:
27
+ | LambdaHandler<TEvent, TResult>
28
+ | MiddyfiedHandler<TEvent, TResult, any, any>;
28
29
  }
29
30
 
30
31
  export type RouteNotFoundResponseFn = (input: {
31
- method: string
32
- path: string
33
- }) => never
32
+ method: string;
33
+ path: string;
34
+ }) => never;
34
35
 
35
36
  declare function httpRouterHandler<
36
- TEvent extends
37
- | ALBEvent
38
- | APIGatewayProxyEvent
39
- | APIGatewayProxyEventV2 = APIGatewayProxyEvent,
40
- TResult extends
41
- | ALBResult
42
- | APIGatewayProxyResult
43
- | APIGatewayProxyResultV2 = APIGatewayProxyResult
44
- > (
45
- routes:
46
- | Array<Route<TEvent, TResult>>
47
- | {
48
- routes: Array<Route<TEvent, TResult>>
49
- notFoundResponse: RouteNotFoundResponseFn
50
- }
51
- ): middy.MiddyfiedHandler<TEvent, TResult>
37
+ TEvent extends
38
+ | ALBEvent
39
+ | APIGatewayProxyEvent
40
+ | APIGatewayProxyEventV2 = APIGatewayProxyEvent,
41
+ TResult extends
42
+ | ALBResult
43
+ | APIGatewayProxyResult
44
+ | APIGatewayProxyResultV2 = APIGatewayProxyResult,
45
+ >(
46
+ routes:
47
+ | Array<Route<TEvent, TResult>>
48
+ | {
49
+ routes: Array<Route<TEvent, TResult>>;
50
+ notFoundResponse: RouteNotFoundResponseFn;
51
+ },
52
+ ): middy.MiddyfiedHandler<TEvent, TResult>;
52
53
 
53
- export default httpRouterHandler
54
+ export default httpRouterHandler;
package/index.js CHANGED
@@ -1,144 +1,148 @@
1
- import { createError } from '@middy/util'
1
+ import { createError } from "@middy/util";
2
2
 
3
3
  const defaults = {
4
- routes: [],
5
- notFoundResponse: ({ method, path }) => {
6
- const err = createError(404, 'Route does not exist', {
7
- cause: { package: '@middy/http-router', data: { method, path } }
8
- })
9
- throw err
10
- }
11
- }
4
+ routes: [],
5
+ notFoundResponse: ({ method, path }) => {
6
+ const err = createError(404, "Route does not exist", {
7
+ cause: { package: "@middy/http-router", data: { method, path } },
8
+ });
9
+ throw err;
10
+ },
11
+ };
12
12
  const httpRouteHandler = (opts = {}) => {
13
- if (Array.isArray(opts)) {
14
- opts = { routes: opts }
15
- }
16
- const { routes, notFoundResponse } = { ...defaults, ...opts }
17
-
18
- const routesStatic = {}
19
- const routesDynamic = {}
20
- const enumMethods = methods.concat('ANY')
21
- for (const route of routes) {
22
- let { method, path, handler } = route
23
-
24
- // Prevents `routesType[method][path] = handler` from flagging: This assignment may alter Object.prototype if a malicious '__proto__' string is injected from library input.
25
- if (!enumMethods.includes(method)) {
26
- throw new Error('Method not allowed', {
27
- cause: { package: '@middy/http-router', data: { method } }
28
- })
29
- }
30
-
31
- // remove trailing slash, but not if it's the first one
32
- if (path.endsWith('/') && path !== '/') {
33
- path = path.substr(0, path.length - 1)
34
- }
35
-
36
- // Static
37
- if (path.indexOf('{') < 0) {
38
- attachStaticRoute(method, path, handler, routesStatic)
39
- continue
40
- }
41
-
42
- // Dynamic
43
- attachDynamicRoute(method, path, handler, routesDynamic)
44
- }
45
-
46
- return (event, context, abort) => {
47
- const { method, path } = getVersionRoute[pickVersion(event)]?.(event)
48
-
49
- if (!method) {
50
- throw new Error('Unknown http event format', {
51
- cause: { package: '@middy/http-router', data: { method } }
52
- })
53
- }
54
- if (!path) {
55
- throw new Error('Unknown http event format', {
56
- cause: { package: '@middy/http-router', data: { path } }
57
- })
58
- }
59
-
60
- // Static
61
- if (
62
- Object.hasOwnProperty.call(routesStatic, method) &&
63
- Object.hasOwnProperty.call(routesStatic[method], path)
64
- ) {
65
- const handler = routesStatic[method][path]
66
- return handler(event, context, abort)
67
- }
68
-
69
- // Dynamic
70
- if (Object.hasOwnProperty.call(routesDynamic, method)) {
71
- for (const route of routesDynamic[method] ?? []) {
72
- const match = path.match(route.path)
73
- if (match) {
74
- event.pathParameters = {
75
- ...match.groups,
76
- ...event.pathParameters
77
- }
78
- return route.handler(event, context, abort)
79
- }
80
- }
81
- }
82
-
83
- // Not Found
84
- return notFoundResponse({ method, path })
85
- }
86
- }
87
-
88
- const regexpDynamicWildcards = /\/\{(proxy)\+\}$/
89
- const regexpDynamicParameters = /\/\{([^/]+)\}/g
90
-
91
- const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'] // ANY excluded by design
13
+ let options;
14
+ if (Array.isArray(opts)) {
15
+ options = { routes: opts };
16
+ }
17
+ options ??= opts;
18
+ const { routes, notFoundResponse } = { ...defaults, ...options };
19
+
20
+ const routesStatic = {};
21
+ const routesDynamic = {};
22
+ const enumMethods = methods.concat("ANY");
23
+ for (const route of routes) {
24
+ let { method, path, handler } = route;
25
+
26
+ // Prevents `routesType[method][path] = handler` from flagging: This assignment may alter Object.prototype if a malicious '__proto__' string is injected from library input.
27
+ if (!enumMethods.includes(method)) {
28
+ throw new Error("Method not allowed", {
29
+ cause: { package: "@middy/http-router", data: { method } },
30
+ });
31
+ }
32
+
33
+ // remove trailing slash, but not if it's the first one
34
+ if (path.endsWith("/") && path !== "/") {
35
+ path = path.substr(0, path.length - 1);
36
+ }
37
+
38
+ // Static
39
+ if (path.indexOf("{") < 0) {
40
+ attachStaticRoute(method, path, handler, routesStatic);
41
+ continue;
42
+ }
43
+
44
+ // Dynamic
45
+ attachDynamicRoute(method, path, handler, routesDynamic);
46
+ }
47
+
48
+ return (event, context, abort) => {
49
+ const { method, path } = getVersionRoute[pickVersion(event)](event);
50
+
51
+ if (!method) {
52
+ throw new Error("Unknown http event format", {
53
+ cause: { package: "@middy/http-router", data: { method } },
54
+ });
55
+ }
56
+ if (!path) {
57
+ throw new Error("Unknown http event format", {
58
+ cause: { package: "@middy/http-router", data: { path } },
59
+ });
60
+ }
61
+
62
+ // Static
63
+ if (
64
+ Object.hasOwnProperty.call(routesStatic, method) &&
65
+ Object.hasOwnProperty.call(routesStatic[method], path)
66
+ ) {
67
+ const handler = routesStatic[method][path];
68
+ return handler(event, context, abort);
69
+ }
70
+
71
+ // Dynamic
72
+ if (Object.hasOwnProperty.call(routesDynamic, method)) {
73
+ for (const route of routesDynamic[method] ?? []) {
74
+ const match = path.match(route.path);
75
+ if (match) {
76
+ event.pathParameters = {
77
+ ...match.groups,
78
+ ...event.pathParameters,
79
+ };
80
+ return route.handler(event, context, abort);
81
+ }
82
+ }
83
+ }
84
+
85
+ // Not Found
86
+ return notFoundResponse({ method, path });
87
+ };
88
+ };
89
+
90
+ const regexpDynamicWildcards = /\/\{(proxy)\+\}$/;
91
+ const regexpDynamicParameters = /\/\{([^/]+)\}/g;
92
+
93
+ const methods = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]; // ANY excluded by design
92
94
 
93
95
  const attachStaticRoute = (method, path, handler, routesType) => {
94
- if (method === 'ANY') {
95
- for (const method of methods) {
96
- attachStaticRoute(method, path, handler, routesType)
97
- }
98
- return
99
- }
100
- if (!routesType[method]) {
101
- routesType[method] = {}
102
- }
103
- routesType[method][path] = handler
104
- routesType[method][path + '/'] = handler // Optional `/`
105
- }
96
+ if (method === "ANY") {
97
+ for (const method of methods) {
98
+ attachStaticRoute(method, path, handler, routesType);
99
+ }
100
+ return;
101
+ }
102
+ if (!routesType[method]) {
103
+ routesType[method] = {};
104
+ }
105
+ routesType[method][path] = handler;
106
+ routesType[method][`${path}/`] = handler; // Optional `/`
107
+ };
106
108
 
107
109
  const attachDynamicRoute = (method, path, handler, routesType) => {
108
- if (method === 'ANY') {
109
- for (const method of methods) {
110
- attachDynamicRoute(method, path, handler, routesType)
111
- }
112
- return
113
- }
114
- if (!routesType[method]) {
115
- routesType[method] = []
116
- }
117
- path = path
118
- .replace(regexpDynamicWildcards, '/?(?<$1>.*)')
119
- .replace(regexpDynamicParameters, '/(?<$1>[^/]+)')
120
- path = new RegExp(`^${path}/?$`) // Adds in optional `/`
121
- routesType[method].push({ path, handler })
122
- }
110
+ if (method === "ANY") {
111
+ for (const method of methods) {
112
+ attachDynamicRoute(method, path, handler, routesType);
113
+ }
114
+ return;
115
+ }
116
+ if (!routesType[method]) {
117
+ routesType[method] = [];
118
+ }
119
+ const pathPartialRegExp = path
120
+ .replace(regexpDynamicWildcards, "/?(?<$1>.*)")
121
+ .replace(regexpDynamicParameters, "/(?<$1>[^/]+)");
122
+ // SAST Skipped: Not accessible by users
123
+ // nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp
124
+ const pathRegExp = new RegExp(`^${pathPartialRegExp}/?$`); // Adds in optional `/`
125
+ routesType[method].push({ path: pathRegExp, handler });
126
+ };
123
127
 
124
128
  const pickVersion = (event) => {
125
- // '1.0' is a safer default
126
- return event.version ?? (event.method ? 'vpc' : '1.0')
127
- }
129
+ // '1.0' is a safer default
130
+ return event.version ?? (event.method ? "vpc" : "1.0");
131
+ };
128
132
 
129
133
  const getVersionRoute = {
130
- '1.0': (event) => ({
131
- method: event.httpMethod,
132
- path: event.path
133
- }),
134
- '2.0': (event) => ({
135
- method: event.requestContext.http.method,
136
- path: event.requestContext.http.path
137
- }),
138
- vpc: (event) => ({
139
- method: event.method,
140
- path: event.raw_path.split('?')[0]
141
- })
142
- }
143
-
144
- export default httpRouteHandler
134
+ "1.0": (event) => ({
135
+ method: event.httpMethod,
136
+ path: event.path,
137
+ }),
138
+ "2.0": (event) => ({
139
+ method: event.requestContext.http.method,
140
+ path: event.requestContext.http.path,
141
+ }),
142
+ vpc: (event) => ({
143
+ method: event.method,
144
+ path: event.raw_path.split("?")[0],
145
+ }),
146
+ };
147
+
148
+ export default httpRouteHandler;
package/package.json CHANGED
@@ -1,74 +1,71 @@
1
1
  {
2
- "name": "@middy/http-router",
3
- "version": "6.1.6",
4
- "description": "HTTP event router for the middy framework",
5
- "type": "module",
6
- "engines": {
7
- "node": ">=20"
8
- },
9
- "engineStrict": true,
10
- "publishConfig": {
11
- "access": "public"
12
- },
13
- "module": "./index.js",
14
- "exports": {
15
- ".": {
16
- "import": {
17
- "types": "./index.d.ts",
18
- "default": "./index.js"
19
- },
20
- "require": {
21
- "default": "./index.js"
22
- }
23
- }
24
- },
25
- "types": "index.d.ts",
26
- "files": [
27
- "index.js",
28
- "index.d.ts"
29
- ],
30
- "scripts": {
31
- "test": "npm run test:unit && npm run test:fuzz",
32
- "test:unit": "node --test __tests__/index.js",
33
- "test:fuzz": "node --test __tests__/fuzz.js",
34
- "test:benchmark": "node __benchmarks__/index.js"
35
- },
36
- "license": "MIT",
37
- "keywords": [
38
- "Lambda",
39
- "Middleware",
40
- "Serverless",
41
- "Framework",
42
- "AWS",
43
- "AWS Lambda",
44
- "Middy",
45
- "HTTP",
46
- "API",
47
- "router"
48
- ],
49
- "author": {
50
- "name": "Middy contributors",
51
- "url": "https://github.com/middyjs/middy/graphs/contributors"
52
- },
53
- "repository": {
54
- "type": "git",
55
- "url": "git+https://github.com/middyjs/middy.git",
56
- "directory": "packages/http-router"
57
- },
58
- "bugs": {
59
- "url": "https://github.com/middyjs/middy/issues"
60
- },
61
- "homepage": "https://middy.js.org",
62
- "funding": {
63
- "type": "github",
64
- "url": "https://github.com/sponsors/willfarrell"
65
- },
66
- "dependencies": {
67
- "@middy/util": "6.1.6"
68
- },
69
- "devDependencies": {
70
- "@middy/core": "6.1.6",
71
- "@types/aws-lambda": "^8.10.97"
72
- },
73
- "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
2
+ "name": "@middy/http-router",
3
+ "version": "6.2.0",
4
+ "description": "HTTP event router for the middy framework",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=20"
8
+ },
9
+ "engineStrict": true,
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "module": "./index.js",
14
+ "exports": {
15
+ ".": {
16
+ "import": {
17
+ "types": "./index.d.ts",
18
+ "default": "./index.js"
19
+ },
20
+ "require": {
21
+ "default": "./index.js"
22
+ }
23
+ }
24
+ },
25
+ "types": "index.d.ts",
26
+ "files": ["index.js", "index.d.ts"],
27
+ "scripts": {
28
+ "test": "npm run test:unit && npm run test:fuzz",
29
+ "test:unit": "node --test",
30
+ "test:fuzz": "node --test index.fuzz.js",
31
+ "test:perf": "node --test index.perf.js"
32
+ },
33
+ "license": "MIT",
34
+ "keywords": [
35
+ "Lambda",
36
+ "Middleware",
37
+ "Serverless",
38
+ "Framework",
39
+ "AWS",
40
+ "AWS Lambda",
41
+ "Middy",
42
+ "HTTP",
43
+ "API",
44
+ "router"
45
+ ],
46
+ "author": {
47
+ "name": "Middy contributors",
48
+ "url": "https://github.com/middyjs/middy/graphs/contributors"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/middyjs/middy.git",
53
+ "directory": "packages/http-router"
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/middyjs/middy/issues"
57
+ },
58
+ "homepage": "https://middy.js.org",
59
+ "funding": {
60
+ "type": "github",
61
+ "url": "https://github.com/sponsors/willfarrell"
62
+ },
63
+ "dependencies": {
64
+ "@middy/util": "6.2.0"
65
+ },
66
+ "devDependencies": {
67
+ "@middy/core": "6.2.0",
68
+ "@types/aws-lambda": "^8.10.97"
69
+ },
70
+ "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431"
74
71
  }