serverless-offline 8.7.0 → 9.0.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.
- package/README.md +91 -95
- package/package.json +41 -69
- package/src/ServerlessOffline.js +412 -0
- package/src/config/commandOptions.js +155 -0
- package/src/config/constants.js +22 -0
- package/{dist → src}/config/defaultOptions.js +8 -17
- package/src/config/index.js +4 -0
- package/src/config/supportedRuntimes.js +47 -0
- package/src/events/authCanExecuteResource.js +35 -0
- package/src/events/authFunctionNameExtractor.js +75 -0
- package/src/events/authMatchPolicyResource.js +71 -0
- package/src/events/authValidateContext.js +51 -0
- package/src/events/http/Endpoint.js +135 -0
- package/src/events/http/Http.js +50 -0
- package/src/events/http/HttpEventDefinition.js +20 -0
- package/src/events/http/HttpServer.js +1277 -0
- package/src/events/http/OfflineEndpoint.js +33 -0
- package/src/events/http/authJWTSettingsExtractor.js +70 -0
- package/src/events/http/createAuthScheme.js +176 -0
- package/src/events/http/createJWTAuthScheme.js +106 -0
- package/src/events/http/index.js +1 -0
- package/src/events/http/javaHelpers.js +102 -0
- package/src/events/http/lambda-events/LambdaIntegrationEvent.js +57 -0
- package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +233 -0
- package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +190 -0
- package/src/events/http/lambda-events/VelocityContext.js +147 -0
- package/src/events/http/lambda-events/index.js +4 -0
- package/src/events/http/lambda-events/renderVelocityTemplateObject.js +93 -0
- package/{dist → src}/events/http/parseResources.js +73 -78
- package/src/events/http/payloadSchemaValidator.js +13 -0
- package/{dist → src}/events/http/templates/offline-default.req.vm +0 -0
- package/{dist → src}/events/http/templates/offline-default.res.vm +0 -0
- package/src/events/schedule/Schedule.js +131 -0
- package/src/events/schedule/ScheduleEvent.js +18 -0
- package/src/events/schedule/ScheduleEventDefinition.js +21 -0
- package/src/events/schedule/index.js +1 -0
- package/src/events/websocket/HttpServer.js +69 -0
- package/src/events/websocket/WebSocket.js +52 -0
- package/src/events/websocket/WebSocketClients.js +462 -0
- package/src/events/websocket/WebSocketEventDefinition.js +18 -0
- package/src/events/websocket/WebSocketServer.js +73 -0
- package/src/events/websocket/http-routes/_catchAll/catchAllRoute.js +16 -0
- package/src/events/websocket/http-routes/_catchAll/index.js +1 -0
- package/src/events/websocket/http-routes/connections/ConnectionsController.js +28 -0
- package/src/events/websocket/http-routes/connections/connectionsRoutes.js +70 -0
- package/src/events/websocket/http-routes/connections/index.js +1 -0
- package/src/events/websocket/http-routes/index.js +2 -0
- package/src/events/websocket/index.js +1 -0
- package/src/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +65 -0
- package/src/events/websocket/lambda-events/WebSocketConnectEvent.js +68 -0
- package/src/events/websocket/lambda-events/WebSocketDisconnectEvent.js +31 -0
- package/src/events/websocket/lambda-events/WebSocketEvent.js +29 -0
- package/src/events/websocket/lambda-events/WebSocketRequestContext.js +67 -0
- package/src/events/websocket/lambda-events/index.js +4 -0
- package/src/index.js +12 -0
- package/src/lambda/HttpServer.js +108 -0
- package/src/lambda/Lambda.js +68 -0
- package/src/lambda/LambdaContext.js +33 -0
- package/src/lambda/LambdaFunction.js +308 -0
- package/src/lambda/LambdaFunctionPool.js +109 -0
- package/src/lambda/__tests__/LambdaContext.test.js +30 -0
- package/src/lambda/__tests__/LambdaFunction.test.js +196 -0
- package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js +47 -0
- package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js +46 -0
- package/src/lambda/__tests__/fixtures/Lambda/package.json +3 -0
- package/src/lambda/__tests__/fixtures/lambdaFunction.fixture.js +145 -0
- package/src/lambda/__tests__/fixtures/package.json +3 -0
- package/src/lambda/__tests__/routes/invocations/InvocationsController.test.js +42 -0
- package/src/lambda/handler-runner/HandlerRunner.js +136 -0
- package/src/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +72 -0
- package/src/lambda/handler-runner/child-process-runner/childProcessHelper.js +42 -0
- package/src/lambda/handler-runner/child-process-runner/index.js +1 -0
- package/src/lambda/handler-runner/docker-runner/DockerContainer.js +417 -0
- package/src/lambda/handler-runner/docker-runner/DockerImage.js +35 -0
- package/src/lambda/handler-runner/docker-runner/DockerRunner.js +63 -0
- package/src/lambda/handler-runner/docker-runner/index.js +1 -0
- package/src/lambda/handler-runner/go-runner/GoRunner.js +166 -0
- package/src/lambda/handler-runner/go-runner/index.js +1 -0
- package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +125 -0
- package/src/lambda/handler-runner/in-process-runner/index.js +1 -0
- package/src/lambda/handler-runner/index.js +1 -0
- package/src/lambda/handler-runner/java-runner/JavaRunner.js +114 -0
- package/src/lambda/handler-runner/java-runner/index.js +1 -0
- package/src/lambda/handler-runner/python-runner/PythonRunner.js +138 -0
- package/src/lambda/handler-runner/python-runner/index.js +1 -0
- package/{dist → src}/lambda/handler-runner/python-runner/invoke.py +0 -0
- package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +107 -0
- package/src/lambda/handler-runner/ruby-runner/index.js +1 -0
- package/{dist → src}/lambda/handler-runner/ruby-runner/invoke.rb +0 -0
- package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +70 -0
- package/src/lambda/handler-runner/worker-thread-runner/index.js +1 -0
- package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +29 -0
- package/src/lambda/index.js +1 -0
- package/src/lambda/routes/index.js +2 -0
- package/src/lambda/routes/invocations/InvocationsController.js +102 -0
- package/src/lambda/routes/invocations/index.js +1 -0
- package/src/lambda/routes/invocations/invocationsRoute.js +77 -0
- package/src/lambda/routes/invoke-async/InvokeAsyncController.js +20 -0
- package/src/lambda/routes/invoke-async/index.js +1 -0
- package/src/lambda/routes/invoke-async/invokeAsyncRoute.js +33 -0
- package/src/utils/__tests__/createUniqueId.test.js +18 -0
- package/src/utils/__tests__/formatToClfTime.test.js +14 -0
- package/src/utils/__tests__/generateHapiPath.test.js +46 -0
- package/src/utils/__tests__/lowerCaseKeys.test.js +30 -0
- package/src/utils/__tests__/parseHeaders.test.js +13 -0
- package/src/utils/__tests__/parseMultiValueHeaders.test.js +24 -0
- package/src/utils/__tests__/parseMultiValueQueryStringParameters.test.js +159 -0
- package/src/utils/__tests__/parseQueryStringParameters.test.js +15 -0
- package/src/utils/__tests__/splitHandlerPathAndName.test.js +54 -0
- package/src/utils/__tests__/unflatten.test.js +32 -0
- package/src/utils/checkDockerDaemon.js +19 -0
- package/src/utils/checkGoVersion.js +16 -0
- package/src/utils/createApiKey.js +5 -0
- package/src/utils/createUniqueId.js +5 -0
- package/src/utils/detectExecutable.js +11 -0
- package/{dist → src}/utils/formatToClfTime.js +6 -14
- package/src/utils/generateHapiPath.js +26 -0
- package/src/utils/getHttpApiCorsConfig.js +28 -0
- package/src/utils/index.js +42 -0
- package/src/utils/jsonPath.js +13 -0
- package/src/utils/logRoutes.js +64 -0
- package/src/utils/lowerCaseKeys.js +6 -0
- package/src/utils/parseHeaders.js +14 -0
- package/src/utils/parseMultiValueHeaders.js +27 -0
- package/src/utils/parseMultiValueQueryStringParameters.js +31 -0
- package/src/utils/parseQueryStringParameters.js +15 -0
- package/src/utils/resolveJoins.js +29 -0
- package/src/utils/splitHandlerPathAndName.js +31 -0
- package/src/utils/unflatten.js +11 -0
- package/dist/ServerlessOffline.js +0 -507
- package/dist/checkEngine.js +0 -21
- package/dist/config/commandOptions.js +0 -149
- package/dist/config/constants.js +0 -30
- package/dist/config/index.js +0 -55
- package/dist/config/supportedRuntimes.js +0 -40
- package/dist/debugLog.js +0 -10
- package/dist/events/authCanExecuteResource.js +0 -35
- package/dist/events/authFunctionNameExtractor.js +0 -87
- package/dist/events/authMatchPolicyResource.js +0 -62
- package/dist/events/http/Endpoint.js +0 -171
- package/dist/events/http/Http.js +0 -77
- package/dist/events/http/HttpEventDefinition.js +0 -36
- package/dist/events/http/HttpServer.js +0 -1363
- package/dist/events/http/OfflineEndpoint.js +0 -40
- package/dist/events/http/authJWTSettingsExtractor.js +0 -76
- package/dist/events/http/authValidateContext.js +0 -48
- package/dist/events/http/createAuthScheme.js +0 -184
- package/dist/events/http/createJWTAuthScheme.js +0 -155
- package/dist/events/http/index.js +0 -15
- package/dist/events/http/javaHelpers.js +0 -99
- package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +0 -85
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -244
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -221
- package/dist/events/http/lambda-events/VelocityContext.js +0 -168
- package/dist/events/http/lambda-events/index.js +0 -39
- package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -108
- package/dist/events/http/payloadSchemaValidator.js +0 -13
- package/dist/events/schedule/Schedule.js +0 -182
- package/dist/events/schedule/ScheduleEvent.js +0 -27
- package/dist/events/schedule/ScheduleEventDefinition.js +0 -36
- package/dist/events/schedule/index.js +0 -15
- package/dist/events/websocket/HttpServer.js +0 -112
- package/dist/events/websocket/WebSocket.js +0 -78
- package/dist/events/websocket/WebSocketClients.js +0 -550
- package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
- package/dist/events/websocket/WebSocketServer.js +0 -140
- package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +0 -33
- package/dist/events/websocket/http-routes/_catchAll/index.js +0 -15
- package/dist/events/websocket/http-routes/connections/ConnectionsController.js +0 -45
- package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +0 -95
- package/dist/events/websocket/http-routes/connections/index.js +0 -15
- package/dist/events/websocket/http-routes/index.js +0 -23
- package/dist/events/websocket/index.js +0 -15
- package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +0 -99
- package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +0 -101
- package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +0 -47
- package/dist/events/websocket/lambda-events/WebSocketEvent.js +0 -54
- package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +0 -98
- package/dist/events/websocket/lambda-events/index.js +0 -39
- package/dist/index.js +0 -19
- package/dist/lambda/HttpServer.js +0 -122
- package/dist/lambda/Lambda.js +0 -113
- package/dist/lambda/LambdaContext.js +0 -53
- package/dist/lambda/LambdaFunction.js +0 -391
- package/dist/lambda/LambdaFunctionPool.js +0 -127
- package/dist/lambda/handler-runner/HandlerRunner.js +0 -223
- package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -132
- package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -40
- package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
- package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -517
- package/dist/lambda/handler-runner/docker-runner/DockerImage.js +0 -67
- package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +0 -74
- package/dist/lambda/handler-runner/docker-runner/index.js +0 -15
- package/dist/lambda/handler-runner/go-runner/GoRunner.js +0 -211
- package/dist/lambda/handler-runner/go-runner/index.js +0 -15
- package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -234
- package/dist/lambda/handler-runner/in-process-runner/index.js +0 -15
- package/dist/lambda/handler-runner/index.js +0 -15
- package/dist/lambda/handler-runner/java-runner/JavaRunner.js +0 -151
- package/dist/lambda/handler-runner/java-runner/index.js +0 -15
- package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -180
- package/dist/lambda/handler-runner/python-runner/index.js +0 -15
- package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -148
- package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
- package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -94
- package/dist/lambda/handler-runner/worker-thread-runner/index.js +0 -15
- package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +0 -30
- package/dist/lambda/index.js +0 -15
- package/dist/lambda/routes/index.js +0 -23
- package/dist/lambda/routes/invocations/InvocationsController.js +0 -142
- package/dist/lambda/routes/invocations/index.js +0 -15
- package/dist/lambda/routes/invocations/invocationsRoute.js +0 -90
- package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +0 -38
- package/dist/lambda/routes/invoke-async/index.js +0 -15
- package/dist/lambda/routes/invoke-async/invokeAsyncRoute.js +0 -43
- package/dist/main.js +0 -11
- package/dist/serverlessLog.js +0 -91
- package/dist/utils/checkDockerDaemon.js +0 -27
- package/dist/utils/checkGoVersion.js +0 -27
- package/dist/utils/createApiKey.js +0 -12
- package/dist/utils/createUniqueId.js +0 -14
- package/dist/utils/detectExecutable.js +0 -21
- package/dist/utils/generateHapiPath.js +0 -28
- package/dist/utils/getHttpApiCorsConfig.js +0 -44
- package/dist/utils/index.js +0 -158
- package/dist/utils/jsonPath.js +0 -21
- package/dist/utils/parseHeaders.js +0 -23
- package/dist/utils/parseMultiValueHeaders.js +0 -36
- package/dist/utils/parseMultiValueQueryStringParameters.js +0 -40
- package/dist/utils/parseQueryStringParameters.js +0 -26
- package/dist/utils/resolveJoins.js +0 -34
- package/dist/utils/satisfiesVersionRange.js +0 -20
- package/dist/utils/splitHandlerPathAndName.js +0 -41
- 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
|
+
}
|