serverless-offline 8.8.1 → 9.1.1

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 (234) hide show
  1. package/README.md +112 -44
  2. package/package.json +33 -57
  3. package/src/ServerlessOffline.js +409 -0
  4. package/src/config/commandOptions.js +159 -0
  5. package/src/config/constants.js +22 -0
  6. package/{dist → src}/config/defaultOptions.js +9 -17
  7. package/src/config/index.js +4 -0
  8. package/src/config/supportedRuntimes.js +47 -0
  9. package/src/events/authCanExecuteResource.js +35 -0
  10. package/src/events/authFunctionNameExtractor.js +75 -0
  11. package/src/events/authMatchPolicyResource.js +71 -0
  12. package/src/events/authValidateContext.js +51 -0
  13. package/src/events/http/Endpoint.js +135 -0
  14. package/src/events/http/Http.js +50 -0
  15. package/src/events/http/HttpEventDefinition.js +20 -0
  16. package/src/events/http/HttpServer.js +1242 -0
  17. package/src/events/http/OfflineEndpoint.js +33 -0
  18. package/src/events/http/authJWTSettingsExtractor.js +70 -0
  19. package/src/events/http/createAuthScheme.js +176 -0
  20. package/src/events/http/createJWTAuthScheme.js +106 -0
  21. package/src/events/http/index.js +1 -0
  22. package/src/events/http/javaHelpers.js +102 -0
  23. package/src/events/http/lambda-events/LambdaIntegrationEvent.js +57 -0
  24. package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +233 -0
  25. package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +190 -0
  26. package/src/events/http/lambda-events/VelocityContext.js +147 -0
  27. package/src/events/http/lambda-events/index.js +4 -0
  28. package/src/events/http/lambda-events/renderVelocityTemplateObject.js +93 -0
  29. package/{dist → src}/events/http/parseResources.js +73 -78
  30. package/src/events/http/payloadSchemaValidator.js +13 -0
  31. package/{dist → src}/events/http/templates/offline-default.req.vm +0 -0
  32. package/{dist → src}/events/http/templates/offline-default.res.vm +0 -0
  33. package/src/events/schedule/Schedule.js +131 -0
  34. package/src/events/schedule/ScheduleEvent.js +18 -0
  35. package/src/events/schedule/ScheduleEventDefinition.js +21 -0
  36. package/src/events/schedule/index.js +1 -0
  37. package/src/events/websocket/HttpServer.js +69 -0
  38. package/src/events/websocket/WebSocket.js +52 -0
  39. package/src/events/websocket/WebSocketClients.js +462 -0
  40. package/src/events/websocket/WebSocketEventDefinition.js +18 -0
  41. package/src/events/websocket/WebSocketServer.js +73 -0
  42. package/src/events/websocket/http-routes/_catchAll/catchAllRoute.js +16 -0
  43. package/src/events/websocket/http-routes/_catchAll/index.js +1 -0
  44. package/src/events/websocket/http-routes/connections/ConnectionsController.js +28 -0
  45. package/src/events/websocket/http-routes/connections/connectionsRoutes.js +70 -0
  46. package/src/events/websocket/http-routes/connections/index.js +1 -0
  47. package/src/events/websocket/http-routes/index.js +2 -0
  48. package/src/events/websocket/index.js +1 -0
  49. package/src/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +65 -0
  50. package/src/events/websocket/lambda-events/WebSocketConnectEvent.js +68 -0
  51. package/src/events/websocket/lambda-events/WebSocketDisconnectEvent.js +31 -0
  52. package/src/events/websocket/lambda-events/WebSocketEvent.js +29 -0
  53. package/src/events/websocket/lambda-events/WebSocketRequestContext.js +67 -0
  54. package/src/events/websocket/lambda-events/index.js +4 -0
  55. package/src/index.js +12 -0
  56. package/src/lambda/HttpServer.js +108 -0
  57. package/src/lambda/Lambda.js +68 -0
  58. package/src/lambda/LambdaContext.js +33 -0
  59. package/src/lambda/LambdaFunction.js +309 -0
  60. package/src/lambda/LambdaFunctionPool.js +109 -0
  61. package/src/lambda/__tests__/LambdaContext.test.js +30 -0
  62. package/src/lambda/__tests__/LambdaFunction.test.js +196 -0
  63. package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js +47 -0
  64. package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js +46 -0
  65. package/src/lambda/__tests__/fixtures/Lambda/package.json +3 -0
  66. package/src/lambda/__tests__/fixtures/lambdaFunction.fixture.js +145 -0
  67. package/src/lambda/__tests__/fixtures/package.json +3 -0
  68. package/src/lambda/__tests__/routes/invocations/InvocationsController.test.js +42 -0
  69. package/src/lambda/handler-runner/HandlerRunner.js +136 -0
  70. package/src/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +76 -0
  71. package/src/lambda/handler-runner/child-process-runner/childProcessHelper.js +42 -0
  72. package/src/lambda/handler-runner/child-process-runner/index.js +1 -0
  73. package/src/lambda/handler-runner/docker-runner/DockerContainer.js +419 -0
  74. package/src/lambda/handler-runner/docker-runner/DockerImage.js +35 -0
  75. package/src/lambda/handler-runner/docker-runner/DockerRunner.js +63 -0
  76. package/src/lambda/handler-runner/docker-runner/index.js +1 -0
  77. package/src/lambda/handler-runner/go-runner/GoRunner.js +172 -0
  78. package/src/lambda/handler-runner/go-runner/index.js +1 -0
  79. package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +126 -0
  80. package/src/lambda/handler-runner/in-process-runner/index.js +1 -0
  81. package/src/lambda/handler-runner/index.js +1 -0
  82. package/src/lambda/handler-runner/java-runner/JavaRunner.js +114 -0
  83. package/src/lambda/handler-runner/java-runner/index.js +1 -0
  84. package/src/lambda/handler-runner/python-runner/PythonRunner.js +138 -0
  85. package/src/lambda/handler-runner/python-runner/index.js +1 -0
  86. package/{dist → src}/lambda/handler-runner/python-runner/invoke.py +0 -0
  87. package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +107 -0
  88. package/src/lambda/handler-runner/ruby-runner/index.js +1 -0
  89. package/{dist → src}/lambda/handler-runner/ruby-runner/invoke.rb +0 -0
  90. package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +70 -0
  91. package/src/lambda/handler-runner/worker-thread-runner/index.js +1 -0
  92. package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +29 -0
  93. package/src/lambda/index.js +1 -0
  94. package/src/lambda/routes/index.js +2 -0
  95. package/src/lambda/routes/invocations/InvocationsController.js +102 -0
  96. package/src/lambda/routes/invocations/index.js +1 -0
  97. package/src/lambda/routes/invocations/invocationsRoute.js +77 -0
  98. package/src/lambda/routes/invoke-async/InvokeAsyncController.js +20 -0
  99. package/src/lambda/routes/invoke-async/index.js +1 -0
  100. package/src/lambda/routes/invoke-async/invokeAsyncRoute.js +33 -0
  101. package/src/utils/__tests__/createUniqueId.test.js +18 -0
  102. package/src/utils/__tests__/formatToClfTime.test.js +14 -0
  103. package/src/utils/__tests__/generateHapiPath.test.js +46 -0
  104. package/src/utils/__tests__/lowerCaseKeys.test.js +30 -0
  105. package/src/utils/__tests__/parseHeaders.test.js +13 -0
  106. package/src/utils/__tests__/parseMultiValueHeaders.test.js +24 -0
  107. package/src/utils/__tests__/parseMultiValueQueryStringParameters.test.js +159 -0
  108. package/src/utils/__tests__/parseQueryStringParameters.test.js +15 -0
  109. package/src/utils/__tests__/splitHandlerPathAndName.test.js +54 -0
  110. package/src/utils/__tests__/unflatten.test.js +32 -0
  111. package/src/utils/checkDockerDaemon.js +19 -0
  112. package/src/utils/checkGoVersion.js +16 -0
  113. package/src/utils/createApiKey.js +5 -0
  114. package/src/utils/createUniqueId.js +5 -0
  115. package/src/utils/detectExecutable.js +11 -0
  116. package/{dist → src}/utils/formatToClfTime.js +6 -14
  117. package/src/utils/generateHapiPath.js +26 -0
  118. package/src/utils/getHttpApiCorsConfig.js +28 -0
  119. package/src/utils/index.js +42 -0
  120. package/src/utils/jsonPath.js +13 -0
  121. package/src/utils/logRoutes.js +64 -0
  122. package/src/utils/lowerCaseKeys.js +6 -0
  123. package/src/utils/parseHeaders.js +14 -0
  124. package/src/utils/parseMultiValueHeaders.js +27 -0
  125. package/src/utils/parseMultiValueQueryStringParameters.js +31 -0
  126. package/src/utils/parseQueryStringParameters.js +15 -0
  127. package/src/utils/splitHandlerPathAndName.js +31 -0
  128. package/src/utils/unflatten.js +11 -0
  129. package/CHANGELOG.md +0 -78
  130. package/dist/ServerlessOffline.js +0 -508
  131. package/dist/config/commandOptions.js +0 -149
  132. package/dist/config/constants.js +0 -30
  133. package/dist/config/index.js +0 -55
  134. package/dist/config/supportedRuntimes.js +0 -40
  135. package/dist/debugLog.js +0 -12
  136. package/dist/events/authCanExecuteResource.js +0 -35
  137. package/dist/events/authFunctionNameExtractor.js +0 -87
  138. package/dist/events/authMatchPolicyResource.js +0 -62
  139. package/dist/events/authValidateContext.js +0 -53
  140. package/dist/events/http/Endpoint.js +0 -173
  141. package/dist/events/http/Http.js +0 -77
  142. package/dist/events/http/HttpEventDefinition.js +0 -36
  143. package/dist/events/http/HttpServer.js +0 -1370
  144. package/dist/events/http/OfflineEndpoint.js +0 -38
  145. package/dist/events/http/authJWTSettingsExtractor.js +0 -76
  146. package/dist/events/http/createAuthScheme.js +0 -184
  147. package/dist/events/http/createJWTAuthScheme.js +0 -159
  148. package/dist/events/http/index.js +0 -15
  149. package/dist/events/http/javaHelpers.js +0 -99
  150. package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +0 -87
  151. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -246
  152. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -225
  153. package/dist/events/http/lambda-events/VelocityContext.js +0 -170
  154. package/dist/events/http/lambda-events/index.js +0 -39
  155. package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -111
  156. package/dist/events/http/payloadSchemaValidator.js +0 -13
  157. package/dist/events/schedule/Schedule.js +0 -183
  158. package/dist/events/schedule/ScheduleEvent.js +0 -27
  159. package/dist/events/schedule/ScheduleEventDefinition.js +0 -36
  160. package/dist/events/schedule/index.js +0 -15
  161. package/dist/events/websocket/HttpServer.js +0 -114
  162. package/dist/events/websocket/WebSocket.js +0 -78
  163. package/dist/events/websocket/WebSocketClients.js +0 -577
  164. package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
  165. package/dist/events/websocket/WebSocketServer.js +0 -139
  166. package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +0 -33
  167. package/dist/events/websocket/http-routes/_catchAll/index.js +0 -15
  168. package/dist/events/websocket/http-routes/connections/ConnectionsController.js +0 -45
  169. package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +0 -95
  170. package/dist/events/websocket/http-routes/connections/index.js +0 -15
  171. package/dist/events/websocket/http-routes/index.js +0 -23
  172. package/dist/events/websocket/index.js +0 -15
  173. package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +0 -99
  174. package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +0 -101
  175. package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +0 -47
  176. package/dist/events/websocket/lambda-events/WebSocketEvent.js +0 -54
  177. package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +0 -98
  178. package/dist/events/websocket/lambda-events/index.js +0 -39
  179. package/dist/index.js +0 -15
  180. package/dist/lambda/HttpServer.js +0 -124
  181. package/dist/lambda/Lambda.js +0 -117
  182. package/dist/lambda/LambdaContext.js +0 -53
  183. package/dist/lambda/LambdaFunction.js +0 -390
  184. package/dist/lambda/LambdaFunctionPool.js +0 -127
  185. package/dist/lambda/handler-runner/HandlerRunner.js +0 -195
  186. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -124
  187. package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -49
  188. package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
  189. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -515
  190. package/dist/lambda/handler-runner/docker-runner/DockerImage.js +0 -67
  191. package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +0 -74
  192. package/dist/lambda/handler-runner/docker-runner/index.js +0 -15
  193. package/dist/lambda/handler-runner/go-runner/GoRunner.js +0 -230
  194. package/dist/lambda/handler-runner/go-runner/index.js +0 -15
  195. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -228
  196. package/dist/lambda/handler-runner/in-process-runner/index.js +0 -15
  197. package/dist/lambda/handler-runner/index.js +0 -15
  198. package/dist/lambda/handler-runner/java-runner/JavaRunner.js +0 -153
  199. package/dist/lambda/handler-runner/java-runner/index.js +0 -15
  200. package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -185
  201. package/dist/lambda/handler-runner/python-runner/index.js +0 -15
  202. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -147
  203. package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
  204. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -92
  205. package/dist/lambda/handler-runner/worker-thread-runner/index.js +0 -15
  206. package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +0 -31
  207. package/dist/lambda/index.js +0 -15
  208. package/dist/lambda/routes/index.js +0 -23
  209. package/dist/lambda/routes/invocations/InvocationsController.js +0 -142
  210. package/dist/lambda/routes/invocations/index.js +0 -15
  211. package/dist/lambda/routes/invocations/invocationsRoute.js +0 -90
  212. package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +0 -38
  213. package/dist/lambda/routes/invoke-async/index.js +0 -15
  214. package/dist/lambda/routes/invoke-async/invokeAsyncRoute.js +0 -43
  215. package/dist/main.js +0 -11
  216. package/dist/serverlessLog.js +0 -91
  217. package/dist/utils/checkDockerDaemon.js +0 -27
  218. package/dist/utils/checkGoVersion.js +0 -27
  219. package/dist/utils/createApiKey.js +0 -12
  220. package/dist/utils/createUniqueId.js +0 -14
  221. package/dist/utils/detectExecutable.js +0 -21
  222. package/dist/utils/generateHapiPath.js +0 -28
  223. package/dist/utils/getHttpApiCorsConfig.js +0 -40
  224. package/dist/utils/index.js +0 -165
  225. package/dist/utils/jsonPath.js +0 -21
  226. package/dist/utils/lowerCaseKeys.js +0 -14
  227. package/dist/utils/parseHeaders.js +0 -23
  228. package/dist/utils/parseMultiValueHeaders.js +0 -36
  229. package/dist/utils/parseMultiValueQueryStringParameters.js +0 -40
  230. package/dist/utils/parseQueryStringParameters.js +0 -26
  231. package/dist/utils/resolveJoins.js +0 -36
  232. package/dist/utils/satisfiesVersionRange.js +0 -20
  233. package/dist/utils/splitHandlerPathAndName.js +0 -37
  234. package/dist/utils/unflatten.js +0 -18
@@ -0,0 +1,35 @@
1
+ import authMatchPolicyResource from './authMatchPolicyResource.js'
2
+
3
+ const { isArray } = Array
4
+
5
+ function checkStatementsAgainstResource(Statement, resource, effect) {
6
+ return Statement.some((statement) => {
7
+ const resourceArray = isArray(statement.Resource)
8
+ ? statement.Resource
9
+ : [statement.Resource]
10
+
11
+ return (
12
+ statement.Effect.toLowerCase() === effect.toLowerCase() &&
13
+ resourceArray.some((policyResource) =>
14
+ authMatchPolicyResource(policyResource, resource),
15
+ )
16
+ )
17
+ })
18
+ }
19
+
20
+ export default function authCanExecuteResource(policy, resource) {
21
+ const { Statement } = policy
22
+
23
+ // check for explicit deny
24
+ const denyStatementFound = checkStatementsAgainstResource(
25
+ Statement,
26
+ resource,
27
+ 'Deny',
28
+ )
29
+
30
+ if (denyStatementFound) {
31
+ return false
32
+ }
33
+
34
+ return checkStatementsAgainstResource(Statement, resource, 'Allow')
35
+ }
@@ -0,0 +1,75 @@
1
+ import { log } from '@serverless/utils/log.js'
2
+
3
+ function buildFailureResult(warningMessage) {
4
+ log.warning(warningMessage)
5
+
6
+ return {
7
+ unsupportedAuth: true,
8
+ }
9
+ }
10
+
11
+ function buildSuccessResult(authorizerName) {
12
+ return {
13
+ authorizerName,
14
+ }
15
+ }
16
+
17
+ function handleStringAuthorizer(authorizerString) {
18
+ if (authorizerString.toUpperCase() === 'AWS_IAM') {
19
+ return buildFailureResult(
20
+ 'Serverless Offline does not support the AWS_IAM authorization type',
21
+ )
22
+ }
23
+
24
+ return buildSuccessResult(authorizerString)
25
+ }
26
+
27
+ function handleObjectAuthorizer(authorizerObject) {
28
+ const { arn, authorizerId, name, type } = authorizerObject
29
+
30
+ if (type && type.toUpperCase() === 'AWS_IAM') {
31
+ return buildFailureResult(
32
+ 'Serverless Offline does not support the AWS_IAM authorization type',
33
+ )
34
+ }
35
+
36
+ if (arn) {
37
+ return buildFailureResult(
38
+ `Serverless Offline does not support non local authorizers (arn): ${arn}`,
39
+ )
40
+ }
41
+
42
+ if (authorizerId) {
43
+ return buildFailureResult(
44
+ `Serverless Offline does not support non local authorizers (authorizerId): ${authorizerId}`,
45
+ )
46
+ }
47
+
48
+ if (!name) {
49
+ return buildFailureResult(
50
+ 'Serverless Offline supports local authorizers but authorizer name is missing',
51
+ )
52
+ }
53
+
54
+ return buildSuccessResult(name)
55
+ }
56
+
57
+ export default function authFunctionNameExtractor(endpoint) {
58
+ const { authorizer } = endpoint
59
+
60
+ if (!authorizer) {
61
+ return buildSuccessResult(null)
62
+ }
63
+
64
+ if (typeof authorizer === 'string') {
65
+ return handleStringAuthorizer(authorizer)
66
+ }
67
+
68
+ if (typeof authorizer === 'object') {
69
+ return handleObjectAuthorizer(authorizer)
70
+ }
71
+
72
+ return buildFailureResult(
73
+ 'Serverless Offline supports only local authorizers defined as string or object',
74
+ )
75
+ }
@@ -0,0 +1,71 @@
1
+ function parseResource(resource) {
2
+ const [, region, accountId, restApiId, path] = resource.match(
3
+ /arn:aws:execute-api:(.*?):(.*?):(.*?)\/(.*)/,
4
+ )
5
+
6
+ return {
7
+ accountId,
8
+ path,
9
+ region,
10
+ restApiId,
11
+ }
12
+ }
13
+
14
+ export default function authMatchPolicyResource(policyResource, resource) {
15
+ // resource and policyResource are ARNs
16
+ if (policyResource === resource) {
17
+ return true
18
+ }
19
+
20
+ if (policyResource === '*') {
21
+ return true
22
+ }
23
+
24
+ if (policyResource === 'arn:aws:execute-api:**') {
25
+ // better fix for #523
26
+ return true
27
+ }
28
+
29
+ if (policyResource === 'arn:aws:execute-api:*:*:*') {
30
+ return true
31
+ }
32
+
33
+ if (policyResource.includes('*') || policyResource.includes('?')) {
34
+ // Policy contains a wildcard resource
35
+
36
+ const parsedPolicyResource = parseResource(policyResource)
37
+ const parsedResource = parseResource(resource)
38
+
39
+ if (
40
+ parsedPolicyResource.region !== '*' &&
41
+ parsedPolicyResource.region !== parsedResource.region
42
+ ) {
43
+ return false
44
+ }
45
+
46
+ if (
47
+ parsedPolicyResource.accountId !== '*' &&
48
+ parsedPolicyResource.accountId !== parsedResource.accountId
49
+ ) {
50
+ return false
51
+ }
52
+
53
+ if (
54
+ parsedPolicyResource.restApiId !== '*' &&
55
+ parsedPolicyResource.restApiId !== parsedResource.restApiId
56
+ ) {
57
+ return false
58
+ }
59
+
60
+ // The path contains stage, method and the path
61
+ // for the requested resource and the resource defined in the policy
62
+ // Need to create a regex replacing ? with one character and * with any number of characters
63
+ const regExp = new RegExp(
64
+ parsedPolicyResource.path.replace(/\*/g, '.*').replace(/\?/g, '.'),
65
+ )
66
+
67
+ return regExp.test(parsedResource.path)
68
+ }
69
+
70
+ return false
71
+ }
@@ -0,0 +1,51 @@
1
+ import Boom from '@hapi/boom'
2
+ import { log } from '@serverless/utils/log.js'
3
+
4
+ const { entries, fromEntries, values } = Object
5
+
6
+ function internalServerError(message) {
7
+ const errorType = 'AuthorizerConfigurationException'
8
+
9
+ const error = Boom.internal()
10
+
11
+ error.output.headers['x-amzn-ErrorType'] = errorType
12
+ error.output.payload.error = errorType
13
+ error.output.payload.message = message
14
+
15
+ return error
16
+ }
17
+
18
+ function isValidContext(context) {
19
+ return values(context).every(
20
+ (value) =>
21
+ typeof value === 'boolean' ||
22
+ typeof value === 'number' ||
23
+ typeof value === 'string',
24
+ )
25
+ }
26
+
27
+ function transform(context) {
28
+ return fromEntries(
29
+ entries(context).map(([key, value]) => [key, String(value)]),
30
+ )
31
+ }
32
+
33
+ export default function authValidateContext(context, authFunName) {
34
+ if (typeof context !== 'object') {
35
+ return internalServerError('Authorizer response context must be an object')
36
+ }
37
+
38
+ if (!isValidContext(context)) {
39
+ const error =
40
+ 'Authorizer response context values must be of type string, number, or boolean'
41
+
42
+ log.notice(
43
+ `Detected invalid value types returned in authorizer context: (λ: ${authFunName}). ${error}. ` +
44
+ 'More info: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html',
45
+ )
46
+
47
+ return internalServerError(error)
48
+ }
49
+
50
+ return transform(context)
51
+ }
@@ -0,0 +1,135 @@
1
+ import { existsSync, readFileSync } from 'node:fs'
2
+ import { dirname, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { log } from '@serverless/utils/log.js'
5
+ import OfflineEndpoint from './OfflineEndpoint.js'
6
+
7
+ const { entries } = Object
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url))
10
+
11
+ // velocity template defaults
12
+ const defaultRequestTemplate = readFileSync(
13
+ resolve(__dirname, './templates/offline-default.req.vm'),
14
+ 'utf8',
15
+ )
16
+ const defaultResponseTemplate = readFileSync(
17
+ resolve(__dirname, './templates/offline-default.res.vm'),
18
+ 'utf8',
19
+ )
20
+
21
+ function getResponseContentType(fep) {
22
+ if (fep.response && fep.response.headers['Content-Type']) {
23
+ return fep.response.headers['Content-Type'].replace(/'/gm, '')
24
+ }
25
+
26
+ return 'application/json'
27
+ }
28
+
29
+ export default class Endpoint {
30
+ #handlerPath = null
31
+
32
+ #http = null
33
+
34
+ constructor(handlerPath, http) {
35
+ this.#handlerPath = handlerPath
36
+ this.#http = http
37
+ }
38
+
39
+ // determine whether we have function level overrides for velocity templates
40
+ // if not we will use defaults
41
+ #setVmTemplates(fullEndpoint) {
42
+ // determine requestTemplate
43
+ // first check if requestTemplate is set through serverless
44
+ const fep = fullEndpoint
45
+
46
+ try {
47
+ // determine request template override
48
+ const reqFilename = `${this.#handlerPath}.req.vm`
49
+
50
+ // check if serverless framework populates the object itself
51
+ if (
52
+ typeof this.#http.request === 'object' &&
53
+ typeof this.#http.request.template === 'object'
54
+ ) {
55
+ const templatesConfig = this.#http.request.template
56
+
57
+ entries(templatesConfig).forEach(([key, value]) => {
58
+ fep.requestTemplates[key] = value
59
+ })
60
+ }
61
+ // load request template if exists if not use default from serverless offline
62
+ else if (existsSync(reqFilename)) {
63
+ fep.requestTemplates['application/json'] = readFileSync(
64
+ reqFilename,
65
+ 'utf8',
66
+ )
67
+ } else {
68
+ fep.requestTemplates['application/json'] = defaultRequestTemplate
69
+ }
70
+
71
+ // determine response template
72
+ const resFilename = `${this.#handlerPath}.res.vm`
73
+
74
+ fep.responseContentType = getResponseContentType(fep)
75
+ log.debug('Response Content-Type ', fep.responseContentType)
76
+
77
+ // load response template from http response template, or load file if exists other use default
78
+ if (fep.response && fep.response.template) {
79
+ fep.responses.default.responseTemplates[fep.responseContentType] =
80
+ fep.response.template
81
+ } else if (existsSync(resFilename)) {
82
+ fep.responses.default.responseTemplates[fep.responseContentType] =
83
+ readFileSync(resFilename, 'utf8')
84
+ } else {
85
+ fep.responses.default.responseTemplates[fep.responseContentType] =
86
+ defaultResponseTemplate
87
+ }
88
+ } catch (err) {
89
+ log.debug(`Error: ${err}`)
90
+ }
91
+
92
+ return fep
93
+ }
94
+
95
+ // loosely based on:
96
+ // https://github.com/serverless/serverless/blob/v1.59.2/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js#L380
97
+ #getIntegration(http) {
98
+ const { integration, async: isAsync } = http
99
+ if (integration) {
100
+ const normalizedIntegration = integration.toUpperCase().replace('-', '_')
101
+ if (normalizedIntegration === 'LAMBDA') {
102
+ return 'AWS'
103
+ }
104
+ if (normalizedIntegration === 'LAMBDA_PROXY') {
105
+ return 'AWS_PROXY'
106
+ }
107
+ return normalizedIntegration
108
+ }
109
+
110
+ if (isAsync) {
111
+ return 'AWS'
112
+ }
113
+
114
+ return 'AWS_PROXY'
115
+ }
116
+
117
+ // return fully generated Endpoint
118
+ generate() {
119
+ const offlineEndpoint = new OfflineEndpoint()
120
+
121
+ const fullEndpoint = {
122
+ ...offlineEndpoint,
123
+ ...this.#http,
124
+ }
125
+
126
+ fullEndpoint.integration = this.#getIntegration(this.#http)
127
+
128
+ if (fullEndpoint.integration === 'AWS') {
129
+ // determine request and response templates or use defaults
130
+ return this.#setVmTemplates(fullEndpoint)
131
+ }
132
+
133
+ return fullEndpoint
134
+ }
135
+ }
@@ -0,0 +1,50 @@
1
+ import HttpEventDefinition from './HttpEventDefinition.js'
2
+ import HttpServer from './HttpServer.js'
3
+
4
+ export default class Http {
5
+ #httpServer = null
6
+
7
+ constructor(serverless, options, lambda) {
8
+ this.#httpServer = new HttpServer(serverless, options, lambda)
9
+ }
10
+
11
+ start() {
12
+ return this.#httpServer.start()
13
+ }
14
+
15
+ // stops the server
16
+ stop(timeout) {
17
+ return this.#httpServer.stop(timeout)
18
+ }
19
+
20
+ #createEvent(functionKey, rawHttpEventDefinition, handler) {
21
+ const httpEvent = new HttpEventDefinition(rawHttpEventDefinition)
22
+
23
+ this.#httpServer.createRoutes(functionKey, httpEvent, handler)
24
+ }
25
+
26
+ create(events) {
27
+ events.forEach(({ functionKey, handler, http }) => {
28
+ this.#createEvent(functionKey, http, handler)
29
+ })
30
+
31
+ this.#httpServer.writeRoutesTerminal()
32
+ }
33
+
34
+ createResourceRoutes() {
35
+ this.#httpServer.createResourceRoutes()
36
+ }
37
+
38
+ create404Route() {
39
+ this.#httpServer.create404Route()
40
+ }
41
+
42
+ registerPlugins() {
43
+ return this.#httpServer.registerPlugins()
44
+ }
45
+
46
+ // TEMP FIXME quick fix to expose gateway server for testing, look for better solution
47
+ getServer() {
48
+ return this.#httpServer.getServer()
49
+ }
50
+ }
@@ -0,0 +1,20 @@
1
+ const { assign } = Object
2
+
3
+ export default class HttpEventDefinition {
4
+ constructor(rawHttpEventDefinition) {
5
+ let method
6
+ let path
7
+ let rest
8
+
9
+ if (typeof rawHttpEventDefinition === 'string') {
10
+ ;[method, path] = rawHttpEventDefinition.split(' ')
11
+ } else {
12
+ ;({ method, path, ...rest } = rawHttpEventDefinition)
13
+ }
14
+
15
+ this.method = method
16
+ this.path = path
17
+
18
+ assign(this, rest)
19
+ }
20
+ }