API Gateway Websockets not sending to all clients - websocket

I'm using websockets with API Gateway and dynamoDB to maintain all connection IDs.
What I'm trying to do is when a new message comes in, a message is sent to all connected clients.
For example, inside the $default route a message will be received from the client. I'm then querying dynamo to get all connected ids and sending that message.
Querying dynamo:
const params = {
TableName: process.env.CONNECTIONS_TABLE,
IndexName: process.env.CONNECTIONS_COMPANY_INDEX,
KeyConditionExpression: "company = :company",
ExpressionAttributeValues: {
":company": data.company,
},
};
const response = await dynamodb.query(params).promise();
response.Items.forEach(async (item) => {
try {
await apig
.postToConnection({
ConnectionId: item.connectionId,
Data: JSON.stringify(data),
})
.promise();
} catch (e) {
if (e.statusCode === 410) {
console.log(e)
}
}
});
The issue I'm having is that it's only received on the clients after the second attempt. So the client sends a message "123" (the above code is run successfully and I've verified it's getting all connections, no errors) but nothing is received by the client. The client sends another message - "456", now both clients will receive the "123" message.
Any ideas why this would happen? I'd expect that each message sent, would receive the same message to all connected clients, not delayed and always one behind.
Thank you!

i faced with exact same issue. Then i just Remove integration response from the API gateway and leave the function return {}
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-routes-integrations.html#apigateway-websocket-api-overview-integrations-differences
In the HTTP protocol, in which requests and responses are sent
synchronously; communication is essentially one-way. In the WebSocket
protocol, communication is two-way. Responses are asynchronous and are
not necessarily received by the client in the same order as the
client's messages were sent. In addition, the backend can send
messages to the client.

Related

Jmeter Websocket socket.io request not received in Nestjs

I have a Nestjs server i am able to send connection request using the below code
const io = require('socket.io-client');
const socket = io("http://localhost:3000", {
transports: ["websocket"],
pingTimeout: 10000,
pingInterval: 25000,
});
const someDelay = 10;
socket.on('connect', function () {
console.log('connected...');
})
The request is received successfully. The issue is when sending the same request using JMETER it never reaches the server
after opening the connection i am sending a request with token and it never reaches server
It doesn't give any error but never reaches server
Following is the error on request-response-sampler
Because you're only opening a connection, you're not sending any "request", consider adding either a single-write sampler or request-response sampler and you should see the request "reaching" the server.
See Basic request-response sample.jmx example test plan and JMeter WebSocket Samplers - A Practical Guide for more information.

Alexa sends SessionEndedRequest on timeout then displays error card to user

While testing my skill, if I do not reply and it times out, Alexa sends a SessionEndedRequest to my Lambda function.
Based on these docs: Handle Requests Sent by Alexa:
Your service cannot send back a response to a SessionEndedRequest.
Therefore, I am not responding to these requests.
But then my app shows a card with this message:
Skill response was marked as failure
(Skill Name)
Request Identifier: amzn1.echo-api.request.xxxxxxxxxxxxxxxxxxxxx
The target Lambda application returned a failure response
So what should we handle this request that does not give a response, and does not result in this error?
I use Node.js in Lambda, but a Python answer is fine too.
Are you sure the error in the card was for SessionEndedRequest only?
Generally, even if you send a response back to Alexa for a SessionEndedRequest, it won't be spoken.
You can handle a SessionEndedRequest like this in ask-nodejs-sdk-v2.
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
console.log("Inside SessionEndedRequestHandler");
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
console.log(`Session ended with reason: ${JSON.stringify(handlerInput.requestEnvelope)}`);
return handlerInput.responseBuilder.getResponse();
},
};

How to prioritize the reponse over request in ASP.NET Web Api

I have a code that looks something like this:
class SomeController {
HttpClient client = new HttpClient();
public Task<dynamic> SomeAction() {
Task.Run<dynamic>(() => {
var response = client.GetAsync(new Uri(someUrl));
return response.ReadAsAsync<dynamic>().Result;
});
}
}
Now, I call this api with many requests (around 300) and the 'someUrl' returns the response after about 200ms.
After adding some console logs I can see a behavior:
All the 200 requests arrive and request the someUrl resource
The first 2-3 requests to someUrl are handled and returned properly
Other responses are waiting for all the 300 requests to arrive and only then they are returned back...
I have heard that there is no prioritization of responses over incoming requests in situations like these but it seems weird to me. It seems like the requests coming to my server and the responses that are coming from the someUrl are on the same queue and until all the requests are sent no response can be handled.
Anyone else encountered this situation? Anyone knows how to handle it properly?
Thanks!

Ruby: Make a call from browser using Twilio

I want to call from my browser to customer phone number using Twilio. I am using toturial of Twilio. I have already an account that I am using for sending sms to my users. Now I want to make phone calls too. This is the code that I am using at my controller
account_sid = "My Twilio account SID"
auth_token = "My Twilio auth"
sender = "My Twilio from number"
capability = Twilio::Util::Capability.new account_sid, auth_token
capability.allow_client_outgoing "My Twilio Twiml app sid"
#capability.allow_client_incoming "jenny"
#token = capability.generate
And this is the javascript code
Twilio.Device.setup("<%= #token %>", {debug: true});
Twilio.Device.ready(function (device) {
$("#log").text("Ready");
});
Twilio.Device.error(function (error) {
$("#log").text("Error: " + error.message);
});
Twilio.Device.connect(function (conn) {
$("#log").text("Successfully established call");
});
Twilio.Device.disconnect(function (conn) {
$("#log").text("Call ended");
});
Twilio.Device.incoming(function (conn) {
$("#log").text("Incoming connection from " + conn.parameters.From);
// accept the incoming connection and start two-way audio
conn.accept();
});
function call() {
// get the phone number to connect the call to
params = {"PhoneNumber": $("#number").val()};
Twilio.Device.connect(params);
}
function hangup() {
Twilio.Device.disconnectAll();
}
But when I try to load my page, it gives me Error: No valid account. I have double checked my credentials and same credentials are successfully sending sms but here it is creating problem. Can any one guide me what Am I doing wrong?
I am doing it on localhost
Megan from Twilio here. You mention you're on localhost. You would need to make your URL publicly accessible. If you're not ready for production, testing with something like Ngrok will allow you to tunnel your localhost to a publicly available URL.

SignalR and failed websocket connection, but still works

I am currently getting this error below in Chrome console, but it still connects successfully with SignalR. Any reason why I am getting this error?
JS Hub Connection
scheduleHub = $.connection.scheduleHub;
scheduleHub.client.viewing = function (name, message) {
app.showWarning(message, name, function () {
app.refreshHash();
});
};
if ($.connection.hub && $.connection.hub.state === $.signalR.connectionState.disconnected) {
$.connection.hub.qs = { "eventid": options.eventId };
$.connection.hub.start()
.done(function () {
alert('Connected');
//scheduleHub.server.viewing('wow', 'test');
})
.fail(function() { alert('Could not Connect!'); });
}
Chrome Console
WebSocket connection to 'ws://localhost:2222/signalr/connect?transport=webSockets&clientProtocol=1.4&eventid=23919&connectionToken=CV3wchrj88t6FdjgA%2BREdzEDIw0rhW6r2aUrb%2BI8qInsb3Y9BqQSOscPxfAZ2g0Dxl704usqdBBn%2BNSFKpjVNOtwASndOweD1kGWPCkWEbtJBMu%2B&connectionData=%5B%7B%22name%22%3A%22schedulehub%22%7D%5D&tid=5' failed: Error during WebSocket handshake: Unexpected response code: 500
Web Sockets initially starts by negotiating the websockets connection over HTTP. During this HTTP handshake, the web server probably raised an exception, anyway, it returns HTTP Status Code 500. Without a successful HTTP response, Chrome is unable to continue negotiating the web sockets connection.
Since SignalR works over multiple transports, and not just websockets, once websockets connection failed, it will have automatically have switched to try some other transport, like forever frame or polling, which is why your connection still works.

Resources