AWS API Gateway -> Lambda -> Github Pages - amazon-web-services

I am trying to point a domain to Github pages site.
I am very new to working with domains and AWS services so I am finding it difficult to troubleshoot issues.
I have created an AWS ApiGateway that points to a lambda function which I would like to use to serve the content from Github pages, but currently, it is giving me the error:
{"message":"Internal Server Error"}
so when trying to fix this issue, I found instructions to make it log additional debug information. (instructions found at: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-troubleshooting-lambda.html)
this is telling me that my configuration for the lambda function is incorrect.
The response from the Lambda function doesn't match the format that API Gateway expects. Lambda body contains the wrong type for field "headers"
I don't know what is expected so I don't know what needs to be changed... my entire lambda function is configured as:
exports.handler = async (event, context, callback) => {
let domain = 'https://github-org-name.github.io/my-repo-with-gh-pages/';
return {
statusCode: '301',
statusDescription: 'Moved Permanently',
headers: {
'location': [{
key: 'Location',
value: domain,
}],
'cache-control': [{
key: 'Cache-Control',
value: "max-age=3600"
}]
},
}
};
I am completely new to using AWS services, so I don't know if anything else needs to be configured. any help is appreciated.

The values in your headers dict must be strings, e.g:
{
"cookies" : ["cookie1", "cookie2"],
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headername": "headervalue", ... },
"body": "Hello from Lambda!"
}
See the bottom of this page:
https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html

Related

Adding allow all to 'Access-Control-Allow-Origin' header in AWS Gateway response using CDK

I am using CDK to create API endpoints. I would like to set 'Access-Control-Allow-Origin' to allow all in the header responses. Here is what I have tried
api.addGatewayResponse('4xx-error-response', {
type: ResponseType.DEFAULT_4XX ,
statusCode: '400',
responseHeaders: {
'Access-Control-Allow-Origin': `*`
},
templates: {
'application/json': '{ "message": "Access denied", "statusCode": "403", "type": "$context.error.responseType" }'
}
});
When I try to deploy this, I get the following error
Resource handler returned message: "Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: *]
Question: How do I add a gateway response like in the below screenshot using CDK
try this way:
const resource = api.addGatewayResource('MyResource', {params...});
resource.addCorsPreflight({
allowOrigins: api.Cors.ALL_ORIGINS // eqivalent to ['*']
allowCredentials: true, // optional for credentials
});
According to the AWS CORS docs You need to set more than one header, so I would just use the method that is doing that for me.
The CDK test directories are a good source of information, next to the official docs. You may find there some useful examples. Here the ApiGateway insides.
in response header instead of * for Access-Control-Allow-Origin you'll have to use '*'.
Like this:
api.addGatewayResponse('invalid-endpoint-error-response', {
type: ResponseType.MISSING_AUTHENTICATION_TOKEN,
statusCode: '500',
responseHeaders: {
'Access-Control-Allow-Origin': "'*'",
},
templates: {
'application/json': '{ "message": $context.error.messageString, "statusCode": "488", "type": "$context.error.responseType" }'
}
});

How to redirect to a new domain using API Gateway with URL params?

I've been using API Gateway to create free HTTPS redirects from one domain to another. But today, I need to include all the URL parameters in the redirect. For example:
example.com/articles/fun-article?source=google&something=else
to
www.example.com/articles/fun-article?source=google&something=else
I was going over the CloudFormation API Gateway docs and couldn't find anything that could allow me to do so. And I was wondering if I'm missing something. So, for example here is the part of the CFN that does the redirect:
"x-amazon-apigateway-integration": {
"type": "mock",
"responses": {
"301": {
"statusCode": "301",
"responseParameters": {
"method.response.header.Location": "'https://tmmwith.us/'"
}
}
},
"requestTemplates": {
"application/json": "{\"statusCode\": 301}"
},
"passthroughBehavior": "when_no_match"
}
In the AWS::ApiGateway::RestApi resource, any ideas if there is a way to mention in the method.response.header.Location to include all the parameters of the URL?

Can the "queryStringParameter" in the eventbody of a GET request be moved to the "body" of the event for an AWS API Gateway HTTP API?

I'm trying to get my "queryStringParameters" in the event into the "body" key of the event so I can parse them in the same way that I parse post requests. Is this possible with a HTTP api? I tried using parameter mappings in the integration settings but this only allows me to append the body to the queryString.
The way that you get the values from a POST request using body and with query parameters are different. So both ca not be in the body property as you want.
The queryStringParameters is passed when you add a URL Query String Parameter in your Api gateway resource.
When you send a request to the event in your API the following event will be send to the Lamba function
{
"resource": "/{proxy+}",
"path": "/path/to/resource",
"httpMethod": "POST",
"isBase64Encoded": true,
"queryStringParameters": {
"foo": "bar"
},
"multiValueQueryStringParameters": {
"foo": [
"bar"
]
},
"pathParameters": {
"proxy": "/path/to/resource"
},
"stageVariables": {
"baz": "qux"
},
"body":"{ \"time\": \"evening\" }",
"headers": {
...
},
...
}
You be able to get the query parameters of event in your Lambda using the properties:
event.queryStringParameters && event.queryStringParameters.foo
And the body we need to get with the body property:
if (event.body) {
let body = JSON.parse(event.body)
if (body.time)
time = body.time;
}
In this way in your Lambda you need to parse them in different ways.
For more information of how to work with API Gateway and Lambda take a look here: Tutorial: Build a Hello World REST API with Lambda proxy integration

Sending http request from aws lambda to google firebse funcitons

I have set up firebase functions to receive http requests and have verified that the same is working. Now im trying to send http request to firebase from aws lambda function. But there is no response either in aws lambda or in the firebase functions log. This is my aws lambda code:
const postData = JSON.stringify({
"queryresult" : {
"parameters": {
"on": "1",
"device": "1",
"off": ""
}
}
});
const options = {
hostname: 'https://<the firebase function endpoint>',
port: 443,
path: '',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = https.request(options, postData)
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
// Write data to request body
req.write(postData);
req.end();
}
The promise part here is suppose to execute the console logs but it is not getting executed. Is there something that i'm missing here. The host is the URL that we obtain when we deploy a function. Or is there some firebase or aws related plan problem. I'am using the spark plan in firebase. Thankyou.

Use multiple same header field in Lambda Proxy Integration

I'm writing a Lambda function that returns a response for Lambda Proxy Integration in Python. The API expects headers to be a dictionary.
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
This requires each header field to be unique, so there is no way to use multiple Set-Cookie's.
I've already tried to convert the dictionary to a list of tuples
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": [ ("headerName": "headerValue"), ... ],
"body": "..."
}
but API gateway complains Malformed Lambda proxy response.
Any idea how to set headers with the same name?
It is currently not possible to send multiple cookies with lambda integration.
If you send multiple set-cookie, then it will take the last one. ok, such a junk implementation right.
Reference, How can I send multiple Set-Cookie headers from API Gateway using a proxied Lambda
Let us see other avaialable options,
Lambda#Edge:
Here is what I find working with Lambda#Edge,
You can create a lambda function for viewer response and modify the header to set cookies.
'use strict';
exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
// send via a single header and split it into multiple set cookie here.
headers['set-Cookie'] = 'cookie1';
headers['Set-Cookie'] = 'cookie2';
callback(null, response);
};
API Gateway Integration Request mapping:
Here is what I found and got working with integration request,
Hope it helps.
Lambda#Edge:
It is possible to set the headers this way:
response.headers['set-cookie'] = [
{ key: 'Set-Cookie', value: 'cookie1=value1' },
{ key: 'Set-Cookie', value: 'cookie2=value2' },
]
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html#lambda-event-structure-response
API Gateway:
Use multiValueHeaders:
response.multiValueHeaders = {
"Set-Cookie": [
'cookie1=value1',
'cookie1=value1'
]
}
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format