API Gateway WebSocket API postConnection timeout - websocket

I'm trying to set up a WebSocket API on API Gateway. I'm following the basic tutorial, and I have everything up and running -> Routes for $connect, $disconnect, "test", $default. I am able to connect to the API, store the connectionId in Redis, and retrieve it when accessing from the test route.
The problem is when I try to send back a message from my lambda (single lambda handling all routes). I'm using the following code
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: `https://${event.requestContext.domainName}/${event.requestContext.stage}`
});
Then I call
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: `Echo: ${data}`
}).promise()
This is only called on the "test" route.
All of this is as per their guide. I had to add a patch to be able to make postConnection work, again, as per their tutorial. The problem is when the above method is called I get a Internal Server Error message from the API Gateway and the lambda times out after 3 seconds.
There is very little info on this method. I'm not sure what is causing the internal server error. I have checked the endpoint and the connectionId, both are correct.
What am I doing wrong? Any suggestions?

So the problem wasn't the actual lambda but the fact that it wasn't set up in a VPC that had access to the Internet. So if you're lambda has VPC enabled, make sure you it has a NAT gateway and Internet gateway set up.

Related

Mastodon subscription/web push API never calls my endpoint

I'm trying to get an AWS Lambda function to be invoked whenever a (bot) Mastodon account is mentioned. I've set up the lambda, API Gateway, and logging such that I can call my function manually:
curl -XPOST -i https://XXXXXX.execute-api.us-east-1.amazonaws.com/mention-hook -d '{"foo":"bar"}'
Each such (manual) call is logged in CloudWatch, and I can see the payload passed.
I've set up a mastodon account and added an application to it (with push permissions), and I'm able to call the api (by passing the application's access token in the header. I'm using Python to register my push hook:
r = requests.post(server + '/api/v1/push/subscription',
headers={'Authorization': 'Bearer {}'.format(token)},
data={'subscription[endpoint]': 'https://XXXXXX.execute-api.us-east-1.amazonaws.com/mention-hook',
'subscription[keys][p256dh]': pKey,
'subscription[keys][auth]': authKey,
'data[alerts][mention]': True,
'policy': 'all' })
and the response (as well as subsequent GETs to /api/v1/push/subscription) look good to me:
200
b'{"id":60703,"endpoint":"https://XXXXXX.execute-api.us-east-1.amazonaws.com/mention-hook","alerts":{"mention":true},"server_key":"[redacted]"}'
Mentioning this account does generate notifications in the web interface and within mobile clients (via their own proxies), but my lambda never gets called.
I've tried the different options for policy as well as all the different kinds of alerts. I've tried this with several different Mastodon servers (all of which successfully deliver pushes to the proxies for mobile clients). I've simply never seen any Mastodon server call my endpoint.

AWS Apigw v2 custom headers not being passed

I've got an API gateway v2 which is using a proxy integration to lambda.
I'm trying to pass a custom header value via a GET call to my API.
...
fetch(new Request(refreshUrl, {
method: 'GET',
headers: new Headers({
'refreshToken': user?.tokens.refreshToken
})
}))
...
I can't for the life of me figure out how to get APIGW to pass that header value to my lambda. When I log the event received in my lambda, my "refreshToken" header is nowhere to be seen.
I've tried to add parameter mapping such as the following to my lambda integration in apigw with no success:
$request.header.refreshtoken
And the documentation for such scenarios with AWS only seems to show for APIGW v1.
Solved:
The issue wasn't related to APIGW. The request parameter mapping is correct.
The problem was that I was proxying the api via cloud front and I needed to whitelist the header in my distribution.

API Gateway and Lambda Proxy integration {"message": "Internal server error"}

I have implemented a solution to integrate API Gateway REST API with AWS Lambda. Lambda function uses two URL Query string parameters for further processing.
When API is tested using the API Gateway console "Test" button I am getting Status Code:200. But when I invoke API from a EC2 Linux machine I am getting {"message": "Internal server error"}.
On checking the logs: Only one URL Query parameter string is passed to Lambda "Event" and the second parameter is lost.
Can anyone suggest what can be the reason here ?

Serverless WebSocket route responses

I am using serverless to create a WebSocket service, for which I am able to successfully trigger my WebSocket routes locally, using serverless-offline and for the deployed service.
The issue I am having now is responding to those WS events.
I am able to use AWS.ApiGatewayManagementApi.postToConnection to respond to my local WebSocket events, though I cannot seem to get the return value of my handler to actually send a WebSocket event in response, as these serverless-offline docs and these AWS docs suggest.
The serverless.yml route:
ws-custom:
handler: handler.wsCustom
events:
- websocket:
route: custom
routeResponseSelectionExpression: $default
The handler:
module.exports.wsCustom = async (event) => {
const body = JSON.parse(event.body);
console.log('WebSocket `custom` event!', event);
return {
statusCode: 200,
body: JSON.stringify({ message: `Hello, ${body.name}!` }),
};
}
Invoking the function in my browser JavaScript:
ws.send(JSON.stringify({ 'action': 'custom', 'name': 'kevbot' }));
The result is that my serverless-offline logs (or CloudWatch in the case of the deployed project) will create an event with the log successfully, but my client will receive no events in response.
Does anyone know how I can do this with the return value of the handler?
EDIT:
The problem seems to exist within my serverless-offline setup. I will attempt to get it working locally and will create an issue necessary.
An important point to note when using WebSocket APIs and trying to return a response from your integration back to the client, as mentioned in this doc:
For a route that is configured to use AWS_PROXY or LAMBDA_PROXY integration, communication is one-way, and API Gateway will not pass the backend response through to the route response automatically. For example, in the case of LAMBDA_PROXY integration, the body that the Lambda function returns will not be returned to the client. If you want the client to receive integration responses, you must define a route response to make two-way communication possible.
So, if you are using a proxy integration, then you cannot return a response back to the client. You would have to use the AWS.ApiGatewayManagementApi.postToConnection method to communicate any data.
Alternatively, if you are using a non-proxy integration, then you can set up a route response for your integration.

AWS api gateway - http proxy should take status code from origin

I am currently trying to setup AWS Api Gateway, to proxy to another api, that has fully functional methods, response content, status codes etc. This is fairly simple to setup, but I have noticed that the Api Gateway always returns 200 OK no matter what the origin api responds with.
Fx. if there was a bad request (in the origin api) which results in a error message in JSON and a 400 Bad Request, the Api Gateway will respond with a the exact same error message, but a status code of 200 OK
If I remove all settings from the Message Response in the API Gateway web-interface, I get an internal error in the API Gateway. Can it be true that I have to map all the different status codes from the origin api manually in the Api Gateway?
I would prefer if it was possible to just let the status code (as well as the response, which currently works great) pass through, and not have the Api Gateway touch it in any way.
Proxy integration can be used to achieve this. In this case, it is HTTP Proxy. Lambda Proxy integration can also be used but will need some code logic in lambda. API GW will then return the result as-is.
You are correct that currently when using API Gateway you are required to map all response codes in your integration responses. We have heard this "pass through" request from other customers and we may consider including this in future updates to the service.

Resources