@pulumi/awsx
Version:
[](https://github.com/pulumi/pulumi-awsx/actions) [](https://slack.pulumi.com) [;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAPI = exports.API = void 0;
// These APIs are currently experimental and may change.
const fs = require("fs");
const mime = require("mime");
const fspath = require("path");
const aws = require("@pulumi/aws");
const pulumi = require("@pulumi/pulumi");
const utils_1 = require("../utils");
const apikey_1 = require("./apikey");
const lambdaAuthorizer = require("./lambdaAuthorizer");
function isEventHandler(route) {
return route.eventHandler !== undefined;
}
function isStaticRoute(route) {
return route.localPath !== undefined;
}
function isIntegrationRouteTargetProvider(obj) {
return obj.target instanceof Function;
}
function isIntegrationRoute(route) {
return route.target !== undefined;
}
function isRawDataRoute(route) {
return route.data !== undefined;
}
class API extends pulumi.ComponentResource {
constructor(name, args, opts = {}) {
super("aws:apigateway:x:API", name, {}, opts);
const apiResource = createAPI(this, name, args, opts.parent);
this.restAPI = apiResource.restAPI;
this.deployment = apiResource.deployment;
this.stage = apiResource.stage;
this.apiPolicy = apiResource.apiPolicy;
this.staticRoutesBucket = apiResource.staticRoutesBucket;
this.url = apiResource.url;
this.swaggerLambdas = apiResource.swaggerLambdas;
this.registerOutputs();
}
/**
* Returns the [aws.lambda.Function] an [EventHandlerRoute] points to. This will either be for
* the aws.lambda.Function created on your behalf if the route was passed a normal
* JavaScript/Typescript function, or it will be the [aws.lambda.Function] that was explicitly
* passed in.
*
* [route] and [method] can both be elided if this API only has a single [EventHandlerRoute]
* assigned to it.
*
* [method] can be elided if [route] only has a single [EventHandlerRoute] assigned to it.
*
* This method will throw if the provided [route] and [method] do not resolve to a single
* [aws.lambda.Function]
*/
getFunction(route, method) {
const methods = this.getMethods(route);
if (!methods || methods.size === 0) {
throw new pulumi.ResourceError(`Route '${route}' has no methods defined for it`, this);
}
if (!method) {
if (methods.size === 1) {
for (const m of methods.values()) {
return m;
}
}
throw new pulumi.ResourceError(`Route '${route}' has multiple methods defined for it. Please provide [method].`, this);
}
const result = methods.get(method);
if (!result) {
throw new pulumi.ResourceError(`Route '${route}' does not have method '${method}' defined for it`, this);
}
return result;
}
getMethods(route) {
if (route === undefined) {
if (this.swaggerLambdas.size === 0) {
throw new pulumi.ResourceError(`This Api has no routes to any Functions.`, this);
}
if (this.swaggerLambdas.size === 1) {
for (const map of this.swaggerLambdas.values()) {
return map;
}
}
throw new pulumi.ResourceError(`[route] must be provided as this Api defines multiple routes with Functions.`, this);
}
return this.swaggerLambdas.get(route);
}
}
exports.API = API;
function createAPI(parent, name, args, optsParent) {
let swaggerString;
let swaggerLambdas;
let title;
let staticRoutesBucket;
let apiPolicy;
if (args.swaggerString) {
const swaggerSpec = pulumi.output(args.swaggerString).apply(s => {
const spec = JSON.parse(s);
if (spec.info === undefined) {
spec.info = {};
}
if (spec.info.title === undefined) {
spec.info.title = name;
}
return spec;
});
title = swaggerSpec.info.title;
swaggerString = swaggerSpec.apply(s => JSON.stringify(s));
swaggerLambdas = new Map();
}
else if (args.routes || args.additionalRoutes) {
const result = createSwaggerSpec(parent, name, args.routes || [], pulumi.output(args.additionalRoutes || []), args.gatewayResponses, args.requestValidator, args.apiKeySource, args.staticRoutesBucket);
title = pulumi.output(name);
swaggerString = result.swagger;
swaggerLambdas = result.swaggerLambdas;
staticRoutesBucket = result.staticRoutesBucket;
}
else {
throw new pulumi.ResourceError("API must specify either [swaggerString] or as least one of the [route] options.", optsParent);
}
const stageName = args.stageName || "stage";
const restApiArgs = args.restApiArgs || {};
// Create the API Gateway Rest API, using a swagger spec.
const restAPI = new aws.apigateway.RestApi(name, Object.assign(Object.assign({}, args.restApiArgs), { name: (0, utils_1.ifUndefined)(restApiArgs.name, title), binaryMediaTypes: (0, utils_1.ifUndefined)(restApiArgs.binaryMediaTypes, ["*/*"]), body: swaggerString,
// We pass this in directly, because setting it in the Swagger doesn't cause
// it to take affect, it must be passed directly to the RestAPI constructor as well.
apiKeySource: args.apiKeySource }), { parent });
if (restApiArgs.policy) {
apiPolicy = new aws.apigateway.RestApiPolicy(name, {
restApiId: restAPI.id,
policy: restApiArgs.policy,
}, { parent });
}
// Account for all potential REST API Args that should trigger a redeployment
const version = pulumi.all([restAPI.apiKeySource, restAPI.binaryMediaTypes, restAPI.endpointConfiguration, restAPI.minimumCompressionSize, restAPI.policy, swaggerString])
.apply(([apiKey, binaryMediaTypes, endpointConfig, minimumCompression, policy, swagger]) => (0, utils_1.sha1hash)(JSON.stringify({ apiKey, binaryMediaTypes, endpointConfig, minimumCompression, policy, swagger })));
// Create a deployment of the Rest API.
const deployment = new aws.apigateway.Deployment(name, Object.assign(Object.assign({}, args.deploymentArgs), { restApi: restAPI,
// Note: We set `variables` here because it forces recreation of the Deployment object
// whenever the body hash changes. Because we use a blank stage name above, there will
// not actually be any stage created in AWS, and thus these variables will not actually
// end up anywhere. But this will still cause the right replacement of the Deployment
// when needed. The Stage allocated below will be the stable stage that always points
// to the latest deployment of the API.
variables: { version } }), {
parent,
dependsOn: apiPolicy ? [apiPolicy] : [],
});
const permissions = createLambdaPermissions(parent, restAPI, name, swaggerLambdas);
// Create a stage, which is an addressable instance of the Rest API. Set it to point at the latest deployment.
const stage = new aws.apigateway.Stage(name, Object.assign(Object.assign({}, args.stageArgs), { restApi: restAPI, deployment: deployment, stageName: stageName }), { parent, dependsOn: permissions });
// Expose the URL that the API is served at.
const url = pulumi.interpolate `${stage.invokeUrl}/`;
return {
restAPI,
deployment,
stage,
apiPolicy,
staticRoutesBucket,
url,
swaggerLambdas,
};
}
exports.createAPI = createAPI;
function createLambdaPermissions(parent, restAPI, name, swaggerLambdas) {
const permissions = [];
for (const [path, lambdas] of swaggerLambdas) {
for (const [method, lambda] of lambdas) {
const methodAndPath = `${method === "ANY" ? "*" : method}${path}`;
permissions.push(new aws.lambda.Permission(name + "-" + (0, utils_1.sha1hash)(methodAndPath), {
action: "lambda:invokeFunction",
function: lambda,
principal: "apigateway.amazonaws.com",
// We give permission for this function to be invoked by any stage at the given method and
// path on the API. We allow any stage instead of encoding the one known stage that will be
// deployed by Pulumi because the API Gateway console "Test" feature invokes the route
// handler with the fake stage `test-invoke-stage`.
sourceArn: pulumi.interpolate `${restAPI.executionArn}*/${methodAndPath}`,
}, { parent }));
}
}
return permissions;
}
function createSwaggerSpec(parent, name, routes, additionalRoutes, gatewayResponses, requestValidator, apikeySource, bucketOrArgs) {
// Default API Key source to "HEADER"
apikeySource = apikeySource || "HEADER";
// Set up the initial swagger spec.
const swagger = {
swagger: "2.0",
info: { title: name, version: "1.0" },
paths: {},
"x-amazon-apigateway-binary-media-types": ["*/*"],
// Map paths the user doesn't have access to as 404.
// http://docs.aws.amazon.com/apigateway/latest/developerguide/supported-gateway-response-types.html
"x-amazon-apigateway-gateway-responses": generateGatewayResponses(gatewayResponses),
"x-amazon-apigateway-api-key-source": apikeySource,
};
if (requestValidator) {
swagger["x-amazon-apigateway-request-validators"] = {
ALL: {
validateRequestBody: true,
validateRequestParameters: true,
},
BODY_ONLY: {
validateRequestBody: true,
validateRequestParameters: false,
},
PARAMS_ONLY: {
validateRequestBody: false,
validateRequestParameters: true,
},
};
swagger["x-amazon-apigateway-request-validator"] = requestValidator;
}
const swaggerLambdas = new Map();
// Now add all the routes to it.
// Use this to track the API's authorizers and ensure any authorizers with the same name
// reference the same authorizer.
const apiAuthorizers = {};
let staticRoutesBucket;
// First, process the routes that create contingent resources.
for (const route of routes) {
checkRoute(parent, route, "path");
// We allow paths to be provided that don't start with / just for convenience. But we always
// normalize them internally to start with / as that it what swagger requires.
if (!route.path.startsWith("/")) {
route.path = "/" + route.path;
}
if (isEventHandler(route)) {
addEventHandlerRouteToSwaggerSpec(parent, name, swagger, swaggerLambdas, route, apiAuthorizers);
}
else if (isStaticRoute(route)) {
if (!staticRoutesBucket) {
staticRoutesBucket = pulumi.Resource.isInstance(bucketOrArgs)
? bucketOrArgs
: new aws.s3.Bucket(safeS3BucketName(name), bucketOrArgs, { parent });
}
addStaticRouteToSwaggerSpec(parent, name, swagger, route, staticRoutesBucket, apiAuthorizers);
}
else if (isIntegrationRoute(route) || isRawDataRoute(route)) {
addIntegrationOrRawDataRouteToSwaggerSpec(route);
}
else {
const exhaustiveMatch = route;
throw new Error("Non-exhaustive match for route");
}
}
const swaggerText = pulumi.all([swagger, additionalRoutes]).apply(([_, routes]) => {
for (const route of routes) {
addIntegrationOrRawDataRouteToSwaggerSpec(route);
}
return pulumi.output(swagger).apply(s => JSON.stringify(s));
});
return { swagger: swaggerText, swaggerLambdas, staticRoutesBucket };
function addIntegrationOrRawDataRouteToSwaggerSpec(route) {
if (isIntegrationRoute(route)) {
addIntegrationRouteToSwaggerSpec(parent, name, swagger, route, apiAuthorizers);
}
else {
addRawDataRouteToSwaggerSpec(parent, name, swagger, route);
}
}
}
function generateGatewayResponses(responses) {
responses = responses || {};
if (!responses["MISSING_AUTHENTICATION_TOKEN"]) {
responses["MISSING_AUTHENTICATION_TOKEN"] = {
"statusCode": 404,
"responseTemplates": {
"application/json": "{\"message\": \"404 Not found\" }",
},
};
}
if (!responses["ACCESS_DENIED"]) {
responses["ACCESS_DENIED"] = {
"statusCode": 404,
"responseTemplates": {
"application/json": "{\"message\": \"404 Not found\" }",
},
};
}
return responses;
}
function addSwaggerOperation(swagger, path, method, operation) {
if (!swagger.paths[path]) {
swagger.paths[path] = {};
}
swagger.paths[path][method] = operation;
}
function checkRoute(parent, route, propName) {
if (route[propName] === undefined) {
throw new pulumi.ResourceError(`Route missing required [${String(propName)}] property`, parent);
}
}
function addEventHandlerRouteToSwaggerSpec(parent, name, swagger, swaggerLambdas, route, apiAuthorizers) {
checkRoute(parent, route, "eventHandler");
checkRoute(parent, route, "method");
const method = swaggerMethod(route.method);
const lambda = aws.lambda.createFunctionFromEventHandler(name + (0, utils_1.sha1hash)(method + ":" + route.path), route.eventHandler, { parent });
const swaggerOperation = createSwaggerOperationForLambda();
addBasePathOptionsToSwagger(parent, swagger, swaggerOperation, route, apiAuthorizers);
addSwaggerOperation(swagger, route.path, method, swaggerOperation);
let lambdas = swaggerLambdas.get(route.path);
if (!lambdas) {
lambdas = new Map();
swaggerLambdas.set(route.path, lambdas);
}
lambdas.set(route.method, lambda);
return;
function createSwaggerOperationForLambda() {
const region = (0, utils_1.getRegion)(parent);
const uri = pulumi.interpolate `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${lambda.arn}/invocations`;
return {
"x-amazon-apigateway-integration": {
uri,
passthroughBehavior: "when_no_match",
httpMethod: "POST",
type: "aws_proxy",
},
};
}
}
function addBasePathOptionsToSwagger(parent, swagger, swaggerOperation, route, apiAuthorizers) {
if (route.authorizers) {
const authRecords = addAuthorizersToSwagger(parent, swagger, route.authorizers, apiAuthorizers);
addAuthorizersToSwaggerOperation(swaggerOperation, authRecords);
}
if (route.requiredParameters) {
addRequiredParametersToSwaggerOperation(swaggerOperation, route.requiredParameters);
}
if (route.requestValidator) {
swaggerOperation["x-amazon-apigateway-request-validator"] = route.requestValidator;
}
if (route.iamAuthEnabled) {
swaggerOperation["x-amazon-apigateway-auth"] = { type: "AWS_IAM" };
}
if (route.apiKeyRequired) {
addAPIkeyToSecurityDefinitions(swagger);
addAPIKeyToSwaggerOperation(swaggerOperation);
}
}
function addAPIkeyToSecurityDefinitions(swagger) {
swagger.securityDefinitions = swagger.securityDefinitions || {};
if (swagger.securityDefinitions["api_key"] && swagger.securityDefinitions["api_key"] !== apikey_1.apiKeySecurityDefinition) {
throw new Error("Defined a non-apikey security definition with the name api_key");
}
swagger.securityDefinitions["api_key"] = apikey_1.apiKeySecurityDefinition;
}
function addAPIKeyToSwaggerOperation(swaggerOperation) {
swaggerOperation.security = swaggerOperation.security || [];
swaggerOperation.security.push({
["api_key"]: [],
});
}
function addAuthorizersToSwagger(parent, swagger, authorizers, apiAuthorizers) {
const authRecords = [];
swagger.securityDefinitions = swagger.securityDefinitions || {};
authorizers = Array.isArray(authorizers) ? authorizers : [authorizers];
for (const auth of authorizers) {
const suffix = Object.keys(swagger.securityDefinitions).length;
const authName = auth.authorizerName || `${swagger.info.title}-authorizer-${suffix}`;
auth.authorizerName = authName;
// Check API authorizers - if its a new authorizer add it to the apiAuthorizers
// if the name already exists, we check that the authorizer references the same authorizer
if (!apiAuthorizers[authName]) {
apiAuthorizers[authName] = auth;
}
else if (apiAuthorizers[authName] !== auth) {
throw new Error("Two different authorizers using the same name: " + authName);
}
// Add security definition if it's a new authorizer
if (!swagger.securityDefinitions[auth.authorizerName]) {
swagger.securityDefinitions[authName] = {
type: "apiKey",
name: auth.parameterName,
in: lambdaAuthorizer.isLambdaAuthorizer(auth) ? auth.parameterLocation : "header",
"x-amazon-apigateway-authtype": lambdaAuthorizer.isLambdaAuthorizer(auth) ? auth.authType : "cognito_user_pools",
"x-amazon-apigateway-authorizer": lambdaAuthorizer.isLambdaAuthorizer(auth)
? getLambdaAuthorizer(parent, authName, auth)
: getCognitoAuthorizer(auth.identitySource, auth.providerARNs),
};
}
const methods = lambdaAuthorizer.isLambdaAuthorizer(auth) || !auth.methodsToAuthorize
? []
: auth.methodsToAuthorize;
authRecords.push({ [authName]: methods });
}
return authRecords;
}
function getCognitoPoolARNs(pools) {
const arns = [];
for (const pool of pools) {
if (pulumi.CustomResource.isInstance(pool)) {
arns.push(pool.arn);
}
else {
arns.push(pool);
}
}
return arns;
}
function getCognitoAuthorizer(identitySource, providerARNs) {
return {
type: "cognito_user_pools",
identitySource: lambdaAuthorizer.getIdentitySource(identitySource),
providerARNs: getCognitoPoolARNs(providerARNs),
};
}
function getLambdaAuthorizer(parent, authorizerName, authorizer) {
if (lambdaAuthorizer.isLambdaAuthorizerInfo(authorizer.handler)) {
const identitySource = lambdaAuthorizer.getIdentitySource(authorizer.identitySource);
let uri;
if (pulumi.CustomResource.isInstance(authorizer.handler.uri)) {
uri = authorizer.handler.uri.invokeArn;
}
else {
uri = authorizer.handler.uri;
}
let credentials;
if (pulumi.CustomResource.isInstance(authorizer.handler.credentials)) {
credentials = authorizer.handler.credentials.arn;
}
else {
credentials = authorizer.handler.credentials;
}
return {
type: authorizer.type,
authorizerUri: uri,
authorizerCredentials: credentials,
identitySource: identitySource,
identityValidationExpression: authorizer.identityValidationExpression,
authorizerResultTtlInSeconds: authorizer.authorizerResultTtlInSeconds,
};
}
// We used to create the lambda and role in an unparented fashion. Pass along an appropriate
// alias to make sure that they can be parented to the api without causing replacements.
const authorizerLambda = aws.lambda.createFunctionFromEventHandler(authorizerName, authorizer.handler, {
parent,
aliases: [{ parent: pulumi.rootStackResource }],
});
const role = lambdaAuthorizer.createRoleWithAuthorizerInvocationPolicy(authorizerName, authorizerLambda, {
parent,
aliases: [{ parent: pulumi.rootStackResource }],
});
const identitySource = lambdaAuthorizer.getIdentitySource(authorizer.identitySource);
return {
type: authorizer.type,
authorizerUri: authorizerLambda.invokeArn,
authorizerCredentials: role.arn,
identitySource: identitySource,
identityValidationExpression: authorizer.identityValidationExpression,
authorizerResultTtlInSeconds: authorizer.authorizerResultTtlInSeconds,
};
}
function addAuthorizersToSwaggerOperation(swaggerOperation, authRecords) {
swaggerOperation.security = swaggerOperation.security || [];
for (const record of authRecords) {
swaggerOperation.security.push(record);
}
}
function addRequiredParametersToSwaggerOperation(swaggerOperation, requiredParameters) {
for (const requiredParam of requiredParameters) {
const param = {
name: requiredParam.name,
in: requiredParam.in,
required: true,
};
swaggerOperation["parameters"] = swaggerOperation["parameters"] || [];
swaggerOperation["parameters"].push(param);
}
}
function addStaticRouteToSwaggerSpec(parent, name, swagger, route, bucket, apiAuthorizers) {
checkRoute(parent, route, "localPath");
const method = swaggerMethod("GET");
// For each static file, just make a simple bucket object to hold it, and create a swagger path
// that routes from the file path to the arn for the bucket object.
//
// For static directories, use greedy api-gateway path matching so that we can map a single api
// gateway route to all the s3 bucket objects we create for the files in these directories.
const stat = fs.statSync(route.localPath);
if (stat.isFile()) {
processFile(route);
}
else if (stat.isDirectory()) {
processDirectory(route);
}
function createRole(key) {
// Create a role and attach it so that this route can access the AWS bucket.
const role = new aws.iam.Role(key, {
assumeRolePolicy: JSON.stringify(apigatewayAssumeRolePolicyDocument),
}, { parent });
const attachment = new aws.iam.RolePolicyAttachment(key, {
role: role,
policyArn: aws.iam.ManagedPolicy.AmazonS3FullAccess,
}, { parent });
return role;
}
function createBucketObject(key, localPath, contentType) {
return new aws.s3.BucketObject(key, {
bucket,
key,
source: new pulumi.asset.FileAsset(localPath),
contentType: contentType || mime.getType(localPath) || undefined,
}, { parent });
}
function processFile(route) {
const key = name + (0, utils_1.sha1hash)(method + ":" + route.path);
const role = createRole(key);
createBucketObject(key, route.localPath, route.contentType);
const swaggerOperation = createSwaggerOperationForObjectKey(key, role);
addBasePathOptionsToSwagger(parent, swagger, swaggerOperation, route, apiAuthorizers);
addSwaggerOperation(swagger, route.path, method, swaggerOperation);
}
function processDirectory(directory) {
const directoryServerPath = route.path.endsWith("/") ? route.path : route.path + "/";
const directoryKey = name + (0, utils_1.sha1hash)(method + ":" + directoryServerPath);
const role = createRole(directoryKey);
let startDir = fspath.isAbsolute(directory.localPath)
? directory.localPath
: fspath.join(process.cwd(), directory.localPath);
if (!startDir.endsWith(fspath.sep)) {
startDir = fspath.join(startDir, fspath.sep);
}
// If the user has supplied 'false' for options.index, then no special index file served
// at the root. Otherwise if they've supplied an actual filename to serve as the index
// file then use what they've provided. Otherwise attempt to serve "index.html" at the
// root (if it exists).
const indexFile = directory.index === false
? undefined
: typeof directory.index === "string"
? directory.index
: "index.html";
const indexPath = indexFile === undefined ? undefined : fspath.join(startDir, indexFile);
// Recursively walk the directory provided, creating bucket objects for all the files we
// encounter.
function walk(dir) {
const children = fs.readdirSync(dir);
for (const childName of children) {
const childPath = fspath.join(dir, childName);
const stats = fs.statSync(childPath);
if (stats.isDirectory()) {
walk(childPath);
}
else if (stats.isFile()) {
// childPath could have either Windows or POSIX separators, so we should account for this.
const childRelativePath = childPath.substr(startDir.length).split(fspath.sep).join(fspath.posix.sep);
const childUrn = directoryKey + "/" + childRelativePath;
createBucketObject(childUrn, childPath);
if (childPath === indexPath) {
// We hit the file that we also want to serve as the index file. Create
// a specific swagger path from the server root path to it.
const swaggerOperation = createSwaggerOperationForObjectKey(childUrn, role);
addBasePathOptionsToSwagger(parent, swagger, swaggerOperation, directory, apiAuthorizers);
swagger.paths[directoryServerPath] = {
[method]: swaggerOperation,
};
}
}
}
}
walk(startDir);
// Take whatever path the client wants to host this folder at, and add the
// greedy matching predicate to the end.
const proxyPath = directoryServerPath + "{proxy+}";
const swaggerOperation = createSwaggerOperationForObjectKey(directoryKey, role, "proxy");
addBasePathOptionsToSwagger(parent, swagger, swaggerOperation, directory, apiAuthorizers);
addSwaggerOperation(swagger, proxyPath, swaggerMethod("ANY"), swaggerOperation);
}
function createSwaggerOperationForObjectKey(objectKey, role, pathParameter) {
const region = (0, utils_1.getRegion)(bucket);
const uri = pulumi.interpolate `arn:aws:apigateway:${region}:s3:path/${bucket.bucket}/${objectKey}${(pathParameter ? `/{${pathParameter}}` : ``)}`;
const result = {
responses: {
"200": {
description: "200 response",
schema: { type: "object" },
headers: {
"Content-Type": { type: "string" },
"content-type": { type: "string" },
},
},
"400": {
description: "400 response",
},
"500": {
description: "500 response",
},
},
"x-amazon-apigateway-integration": {
credentials: role.arn,
uri: uri,
passthroughBehavior: "when_no_match",
httpMethod: "GET",
type: "aws",
responses: {
"4\\d{2}": {
statusCode: "400",
},
"default": {
statusCode: "200",
responseParameters: {
"method.response.header.Content-Type": "integration.response.header.Content-Type",
"method.response.header.content-type": "integration.response.header.content-type",
},
},
"5\\d{2}": {
statusCode: "500",
},
},
},
};
if (pathParameter) {
result.parameters = [{
name: pathParameter,
in: "path",
required: true,
type: "string",
}];
result["x-amazon-apigateway-integration"].requestParameters = {
[`integration.request.path.${pathParameter}`]: `method.request.path.${pathParameter}`,
};
}
return result;
}
}
function addIntegrationRouteToSwaggerSpec(parent, name, swagger, route, apiAuthorizers) {
checkRoute(parent, route, "target");
const target = isIntegrationRouteTargetProvider(route.target)
? pulumi.output(route.target.target(name + (0, utils_1.sha1hash)(route.path), parent))
: pulumi.output(route.target);
// Register two paths in the Swagger spec, for the root and for a catch all under the root
const method = swaggerMethod("ANY");
const swaggerPath = route.path.endsWith("/") ? route.path : route.path + "/";
const swaggerPathProxy = swaggerPath + "{proxy+}";
const swaggerOpWithoutProxyPathParam = createSwaggerOperationForProxy(target, /*useProxyPathParameter:*/ false);
addBasePathOptionsToSwagger(parent, swagger, swaggerOpWithoutProxyPathParam, route, apiAuthorizers);
addSwaggerOperation(swagger, swaggerPath, method, swaggerOpWithoutProxyPathParam);
const swaggerOpWithProxyPathParam = createSwaggerOperationForProxy(target, /*useProxyPathParameter:*/ true);
addBasePathOptionsToSwagger(parent, swagger, swaggerOpWithProxyPathParam, route, apiAuthorizers);
addSwaggerOperation(swagger, swaggerPathProxy, method, swaggerOpWithProxyPathParam);
return;
function createSwaggerOperationForProxy(target, useProxyPathParameter) {
const uri = target.apply(t => {
let result = t.uri;
// ensure there is a trailing `/`
if (!result.endsWith("/")) {
result += "/";
}
if (useProxyPathParameter) {
result += "{proxy}";
}
return result;
});
const connectionType = target.connectionType;
const connectionId = target.connectionId;
const type = (0, utils_1.ifUndefined)(target.type, "http_proxy");
const passthroughBehavior = (0, utils_1.ifUndefined)(target.passthroughBehavior, "when_no_match");
const result = {
"x-amazon-apigateway-integration": {
responses: {
default: {
statusCode: "200",
},
},
uri,
type,
connectionType,
connectionId,
passthroughBehavior,
httpMethod: "ANY",
},
};
if (useProxyPathParameter) {
result.parameters = [{
name: "proxy",
in: "path",
required: true,
type: "string",
}];
result["x-amazon-apigateway-integration"].requestParameters = {
"integration.request.path.proxy": "method.request.path.proxy",
};
}
return result;
}
}
function addRawDataRouteToSwaggerSpec(parent, name, swagger, route) {
checkRoute(parent, route, "data");
checkRoute(parent, route, "method");
// Simply take the [data] part of the route and place it into the correct place in the
// swagger spec "paths" location.
addSwaggerOperation(swagger, route.path, swaggerMethod(route.method), route.data);
}
function swaggerMethod(method) {
switch (method.toLowerCase()) {
case "get":
case "put":
case "post":
case "delete":
case "options":
case "head":
case "patch":
return method.toLowerCase();
case "any":
return "x-amazon-apigateway-any-method";
default:
throw new Error("Method not supported: " + method);
}
}
const apigatewayAssumeRolePolicyDocument = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com",
},
"Action": "sts:AssumeRole",
},
],
};
function safeS3BucketName(apiName) {
return apiName.toLowerCase().replace(/[^a-z0-9\-]/g, "");
}
//# sourceMappingURL=api.js.map