How can I change websocket connection IDs in AWS API Gateway? - amazon-web-services

I am curious how does AWS Websocket ApiGateway generate connectionIDs and if it is possible to customize how they are generated?
$context.connectionId = A unique ID for the connection that can be
used to make a callback to the client.
For example, I would like the connection ID to always have the same value (the user ID in my DB) whenever he is connected.
If user ID = 1 then connection ID should also = 1 and it is the client app responsibility to enforce uniqueness.

No, it is not possible to modify the auto-generated connection ID.
When a WebSocket client requests a new connection, API Gateway assigns an auto-generated connection ID e.g. AjKdsJDkDJfgmDJ= to that session and invokes your $connect Lambda function with the ID in the event payload (event.requestContext.connectionId).
You can't answer How is the connection ID generated? as it's not a GUID nor a number but it's definitely a random value generated by something.
You can use this connection ID to send a message directly back to the client in the same function invocation.
If you want to also be able to send a message later on, store the connection ID in a data store - DynamoDB for example - along with a mapping to your user IDs.
This way, you can look up your table by the user ID & then obtain the connection ID for interacting with them and vice-versa.

Related

How can I publish to subscriber based on connection id via go library `graph-gophers`

I am using graph-gophers library to build graphql application on the server side. I have a lambda works as resolvers and websocket apigateway which works as transport layer. The lambda will take the request from apigateway then call graph-gophers library schema methods to trigger resolver. It works well for query and mutation. But I am not sure how to make it work for subscription.
The library graph-gophers requires the subscription resolver to return a go channels which it listens to. but in case of lambda which is a short lived application, it can't keep alive for a long time. That means I can't use channel for publishing data.
What I am doing is to save the socket connection id on a database, when there is a need to publish data, I will grab the connection id from db to find all the subscribers. But I don't know how to trigger the publish in this case. Anyone has any idea about how to do that?

Can a lambda return a response and wait for a new body without closing the session?

I am running a puppeteer function in AWS Lambda and I have a scenario that the user makes a POST request to the lambda with his username and email. The function is going to check if they are valid in a website and return the JSON to the user with the answer. Is it possible to use the same lambda session to receive another input/body from the user?
The reason I need it to be the same session is because each time an user and email is sent to the lambda, the puppeteer website is going to generate unique ID's that need to be used AFTER the user sends his data in that exact moment because it is logged into the website with an unique session.
I'm currently running this function in a NodeJS and it is fine because the session isnt going to be closed but the session is closed once the lambda returns the first response.
Like people mentioned above, Lambda function is stateless resource and you can ultimately use dynamoDB to store any values such session ID or so.
Additionally, if the Lambda function should wait for response or any updated values by querying DynamoDB, then you can implement AWS Step Function or Airflow which provides the "wait" state.
See what States you can leverage in the AWS Docs.

AWS API Gateway - Is there a way to append metadata to the connection session, so it propagates to disconnect when that is triggered?

So I need to build a WebSocket API for my org. The requirements from the business are pretty typical websocket pattern stuff except for one detail:
This websocket api will be used by different teams in our org, and each team needs its own separate activeconnections dynamodb table.
Now in a typical websocket api, there would be a single connections table that the connect and disconnect lambda functions write/delete to. Also, the hooks in the websocket api ensure that the connectionId needed to identify a connection/session are always in the event.requestContext. Easy peasy for a single connections table.
However, In my approach of having a separate active connections db/table for each team, it gets more complicated. Yes, it's true that for the connect lambda, It is very easy to code so that it expects a "TeamDatabaseID" from somewhere in the initial connection request - Headers, queryStringParameters, etc.
The problem is in the subsequent disconnect that could be triggered from either client or server. The disconnect hook will run the disconnect function, and pass in the default requestContext with the connectionId, but with no TeamDatabaseID - which the disconnect lambda needs to have access to in order to know which database to delete from.
Is there a way to do this? Is there some notion of a context object that I can set values in from the initial connection, so that when the disconnect happens, the teamDatabaseID is propagated in some way to the subsequent disconnect lambda? I tried writing to the requestContext - and that seems to only be alive for the execution of the given lambda.
Instead of having a single Amazon API Gateway Web Socket API for multiple teams, could you instead have one Web Socket API per team?

AWS - SNS (India Text Message) Not sending via Local Routes

Am Using the Java API to try to send SMS to India Numbers.
I have a valid Entity ID and Template ID registered using JIO DLT (https://trueconnect.jio.com/#/)
I am setting Messaage Attributes as following
AWS.SNS.SMS.SMSType - Transactional
AWS.SNS.SMS.SenderID - <My Registered Sender ID>
AWS.MM.SMS.EntityId - <DLT provided Entity ID>
AWS.MM.SMS.TemplateId - <Template ID of the message i want to send>
Am using software.amazon.awssdk.services.sns.SnsClient to send the Request as below...
PublishRequest pb = PublishRequest.builder()
.message(message)
.phoneNumber(snsDefaultCountryCode+to)
.messageAttributes(smsAttributes).build();
PublishResponse result = snsClient.publish(pb);
I do receive the SMS, but via ILDO with international charges. I was expecting the message to go via local routes or at least a response with error 'Entity ID is invalid' or 'Template ID is invalid' etc.
Are there any other steps to do before sending SMS to india using the AWS services?
I believe you need to register the DLT sender id with AWS using a service limit support request on Pinpoint SMS Service.
After AWS support team approves your request, which may take upto 24 hours your SMS will get routed via India with sender id
Please find the reference link for the same here

Sending newly created primary key value back to app using Lambda

My mobile app sends a message to SQS which triggers a Lambda function
that inserts data into a SQL DB.
When it creates the new row, it generates a Primary key. I want to send that
new primary key value to my mobile app before my lambda function is done running.
Should I use SNS to send the value? All opinions appreciated!
A few ideas come to mind:
1) When you mobile app create the SQS message, it should include some sort of callback information in the payload so that the Lambda knows how to reach back to the mobile app and send the primary key information.
2) This sounds like this should be synchronous REST API call. Instead of the mobile app creating a message on a queue, could it instead be invoking your lambda function via a synchronous API Gateway request which can then directly return the primary key to the caller.