I'm build an API using AWS SAM (Lambda & API Gateway) whose contract is defined by a 3rd party.
The 3rd party calls my API with a GET request that contains JSON in the body. However, when a request is sent to the API with a body it gets rejected by CloudFront.
This is the request:
curl -X GET -H "Content-Type: application/json" --data '{"hello":"world"}' https://my-api.execute-api.us-east-2.amazonaws.com/Prod/my-api
This is the response:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD>
<BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: 1p0St_-e3noQL-2uMxeB_2I6lkMr1mg5afvxJRmVpCdnG67Vgnhj9w==
</PRE>
<ADDRESS></ADDRESS>
</BODY>
</HTML>
Checking the logs, the request never hits API Gateway or the Lambda function. However, if I remove the body from the request, then it hits the Lambda function and I get the appropriate error message from the API (telling the caller that the expected body is missing.)
curl -X GET -H "Content-Type: application/json" https://my-api.execute-api.us-east-2.amazonaws.com/Prod/my-api
I'm using basic configuration of API Gateway via a SAM template. This is the relevant section:
MyApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: bin/main.zip
Handler: main
Runtime: go1.x
Tracing: Active
Role: !Sub ${MyApiLambdaExecutorRole.Arn}
Events:
CatchAll:
Type: Api
Properties:
Path: /my-api
Method: GET
To resolve the Request Blocked error when the default action is Block, review the requests to be sure that they match the conditions for any AWS WAF rules with Action set to Allow. If valid requests don't match any existing rules that allow requests, then create a rule that allows the requests.
This will occur because of below reasons: The request is initiated over HTTP, but the CloudFront distribution is configured to only allow HTTPS requests. The requested alternate domain name (CNAME) isn't associated with the CloudFront distribution.
GET
requests cannot contain a request body on CloudFront. Try using POST
instead.
If you want to send limited data in a GET
request, you can use query parameters.
You can see in the AWS Docs that this isn't possible here:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#RequestCustom-get-body
If a viewer GET request includes a body, CloudFront returns an HTTP status code 403 (Forbidden) to the viewer.
You could perhaps use an EC2 instance or other service that doesn't use API Gateway to handle the request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With