Path parameters ignored by AWS API Gateway using proxy+ - amazon-web-services

I have a REST API on the AWS API Gateway. It has one resource, /{proxy+}, that is configured with the ANY method. The integration request is setup to be a VPC_PROXY, meaning its using a VPC Link. The VPC link is to a network load balancer that is fronting an app I have running on an ECS cluster using Fargate.
When using the console's option to test the API, I can confirm that requests are reaching my app but the resource being requested is always / according to my logging. If I attempt to set the {proxy} value in the method test screen on the console, it seems like my app only ever gets requests for /. If I set {proxy} to something like widget/5, the response I receive is as if I was request /.
I'm wondering if there is some way to troubleshoot this, scouring the AWS documentation I can't figure out where I'm going wrong with my setup.

In your integration, the endpoint URL should be http://loadbalancerurl/{proxy}. I couldn't find any documentation specifically for VPC Link integration, but there is a tutorial for HTTP proxy integration which has similar steps.
If you are using openapi spec, the integration section would look something like this:
x-amazon-apigateway-integration:
uri: "http://loadbalancerurl/{proxy}"
responses:
default:
statusCode: "200"
requestParameters:
integration.request.path.proxy: "method.request.path.proxy"
passthroughBehavior: "when_no_match"
connectionType: "VPC_LINK"
connectionId: "your-vpclink-id"
httpMethod: "ANY"
type: "http_proxy"
When using the console, integration.request.path.proxy: "method.request.path.proxy" mapping was added automatically when I added {proxy} to my endpoint URL.

What works for me is by adding the following properties:
Resources:
APIGWProxyMethod:
Type: AWS::ApiGateway::Method
Properties:
RequestParameters:
method.request.path.proxy: true # enable proxy
Integration:
RequestParameters:
integration.request.path.proxy: method.request.path.proxy # map method proxy param to integration proxy param
... # the rest of integration property
... # other properties
Articles that helped:
https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-proxy-path-character-error/
https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-proxy-path-parameter-error/

Related

AWS - API Gateway - adding query string parameter via mapping template?

Is there a way to do this?
My use case
I'm trying to integrate API gateway and SNS, but every guide/tutorial I found get the TopicArn from the gateway incoming requeste, i.e. from the user call, but since my endpoint will push to a single topic I want to avoid this step, having the API gateway adding it (hardcoded) to the integration request.
AFAIK the only way to do this is via mapping template, is that right?
It was easy and probably I was making some typos at the beginning, so that's why I wasn't succeeding.
AWS::ApiGateway::Method Integration property docs
Amazon API Gateway API request and response data mapping reference
Cloudformation template relevant code
Resources:
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
Integration:
RequestParameters:
integration.request.querystring.<query-param-name>:
IntegrationResponses:
- StatusCode: '200'<desired value>
MethodResponses:
- StatusCode: '200'
ResponseModels:
application/json: "Empty"

AWS API Gateway integration with AWS Event Bridge(Cloudwatch Events) in Cloudformation Script

Original Requirement:
Create a route/path on AWS Api Gateway which connects API Gateway directly to AWS Event Bridge (Cloudwatch Events) and puts/pushes event on an event bus of it.
Was able to create it and executes just fine when done from AWS Console.
Actual Problem:
When writing the AWS Cloudformation script for this API Gateway, it looks like this:
EventsPostMethod:
Type: AWS::ApiGateway::Method
Properties:
ResourceId:
Ref: EventsResource
RestApiId:
Ref: RestAPI
HttpMethod: POST
AuthorizationType: NONE
Integration:
Type: AWS
IntegrationHttpMethod: POST
Uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:cloudwatchEvents:action/PutEvents
RequestParameters:
integration.request.header.X-Amz-Target: "'AWSEvents.PutEvents'"
RequestTemplate:
some-script-here...
Notice the Uri value:
"arn:aws:apigateway:${AWS::Region}:cloudwatchEvents:action/PutEvents"
arn:aws:apigateway:{region}:{subdomain.service|service}:path|action/{service_api}
According to AWS Docs the value of uri should be following:
For AWS or AWS_PROXY integrations, the URI is of the form arn:aws:apigateway:{region}:{subdomain.service|service}:path|action/{service_api}. Here, {Region} is the API Gateway region (e.g., us-east-1); {service} is the name of the integrated AWS service (e.g., s3); and {subdomain} is a designated subdomain supported by certain AWS service for fast host-name lookup. action can be used for an AWS service action-based API, using an Action={name}&{p1}={v1}&p2={v2}... query string. The ensuing {service_api} refers to a supported action {name} plus any required input parameters. Alternatively, path can be used for an AWS service path-based API. The ensuing service_api refers to the path to an AWS service resource, including the region of the integrated AWS service, if applicable. For example, for integration with the S3 API of GetObject, the uri can be either arn:aws:apigateway:us-west-2:s3:action/GetObject&Bucket={bucket}&Key={key} or arn:aws:apigateway:us-west-2:s3:path/{bucket}/{key}
You must have noticed that I replaced the service with cloudwatchEvents in the above mentioned uri.
Now, error Given by AWS Cloudformation Console during Publish of API Gateway:
AWS Service of type cloudwatchEvents not supported (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 07bae22c-d198-4595-8de9-6ea23763eff5; Proxy: null)
Now I have tried replacing service with
cloudwatch
eventBridge
cloudwatchEvent
event-bus
This is the real problem. What should I place in service in uri so that it accepts ?
Based on the comments,
The URI should be something like below for events:
arn:aws:apigateway:${AWS::Region}:events:action/PutEvents

AWS SAM: How to use the same API Gateway for both WebSocket and HTTPS lambdas?

I've been using AWS SAM for a websocket API and that's been working well. Today, I needed to add an HTTPS API, however my attempt to do so results in a new API gateway, under a different subdomain, to be created. I'd like them to share the same domain, so users only need to change the protocol (from HTTPS to WSS).
This is a relevant section of my template.yaml:
# This seems to implicitly create and use a `ServerlessRestApi` API gateway
PingLambda:
Type: AWS::Serverless::Function
Properties:
CodeUri: lambda/
Handler: app.pingHandler
Runtime: nodejs12.x
Events:
Ping:
Type: Api
Properties:
Path: /ping
Method: get
# I use this for the various websocket lambdas, works like a charm
WebSocketApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: SimpleRelayWebSocket
ProtocolType: WEBSOCKET
RouteSelectionExpression: \\$default
# ...
# I'd love both of these to use the same subdomain/API gateway setup
Outputs:
APIURL:
Description: URL of the Simple Relay HTTPS API
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}'
WebSocketURL:
Description: URL of the Simple Relay WSS API
Value: !Sub 'wss://${WebSocketApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}'
I'm not sure how to proceed, considering the WebSocketApi has ProtocolType: WEBSOCKET set there. Is there some way to split the API into multiple things with different protocols, or is there something else I'm missing?
I need to do the same thing. One possible solution is to put both behind a CloudFront distribution. I'll do this probably, since I'm already using CloudFront to serve the front-end from S3, and some back-end endpoints.

Using AWS api gateway, how to identify which apis are configured using Lambda proxy integration or Lambda non-proxy (custom) integration

I have APIs configured in AWS API gateway (few with lambda integration and few with lambda proxy integration).
We have decided to go ahead only with lambda proxy integration as it is easy to deploy and maintain. Have exported json file using "Swagger + API Gateway Extensions".
How to identify which endpoints uses lambda integrations from the json file.
Do we have to manually open each endpoint in API Gateway UI and check if it has lambda proxy enabled or there is a better way to identify?
Thanks.
If you look in the Swagger file with custom extensions, each endpoint/method should have a property called x-amazon-apigateway-integration. Underneath that there will be another property named type.
The value for endpoints without Lambda Proxy Integration will be aws and the lambdas with Proxy Integration will be aws_proxy
paths:
# This is not a lambda proxy integration
/v1/noproxy:
get:
produces:
- "application/json"
responses: {}
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:****:function:***/invocations"
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws"
# This is a lambda proxy integration
/v1/myproxyintegration:
post:
responses: {}
security:
- sigv4: []
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:*****:function:***/invocations"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
type: "aws_proxy"

How to configure CORS for an AWS API Gateway Custom Authorizer?

I have an API powered by API Gateway and Lambda that uses a custom authorizer.
For successful requests, it passes through the authorizer and then my Lambda can return proper responses with CORS headers with no problems.
However, for unsuccessful authorizations (eg. invalid tokens), I get no CORS headers and that causes my client app (which uses fetch API) to throw.
How do I setup CORS for an API that uses a custom authorizer?
Based from this answer and this AWS documentation page, I was able to figure out how to solve it.
The solution is to add the following in my serverless.yml:
resources:
Resources:
AuthorizerApiGatewayResponse:
Type: "AWS::ApiGateway::GatewayResponse"
Properties:
ResponseParameters:
"gatewayresponse.header.Access-Control-Allow-Origin": "'*'"
ResponseType: UNAUTHORIZED
RestApiId: {"Ref" : "ApiGatewayRestApi"}
StatusCode: "401"