In aws-sdk gem and Amazon developer docs I tried to find any information about SNS silent pushes, but it seems very contradictorily.
I am confusing that in SNS Client message is required, but is it possible to send exactly silent GCM and APNS notifications?
Does anybody have information about it?
Any advice/resource will be appreciated.
It seems you can send messages to SNS using JSON format, so you should be able to set content-available and set the alert as you wish.
For Android I think it would be the same (but as Android handles notification differently you should be able to handle any payload and don't show the notification)
Yes, the Amazon AWS SNS docs about silent push notifications are not very helpful, but it works.
I am sende silent push notifications via AWS SNS service via Lambda Node.js to iOS devices via Apple APNS
SEND AWS SNS SILENT PUSH NOTIFICATION TO APNS with Node.js
var sns = new AWS.SNS();
var data = {myString:'silent push'}; // payload data object
sns.publish({
TargetArn: snsTopicArn,
MessageStructure: 'json',
Message: JSON.stringify({
default: 'silent push!',
APNS_SANDBOX: JSON.stringify({
aps: {
'alert': '',
'content-available': 1
},
'data': JSON.stringify(data)
})
})
}, function(err, data) {
if (err) {
console.log(err.stack);
return;
}
});
For android, if you don't send "message" inside GCM object it will be a silent push notification. This aligns with the GCM documentation
GCM: {
data: {
// message: 'hello'
}
}
Related
I created an AWS API Gateway route for Websocket connections. I started with the AWS provided Simple Web Chat templates but have modified it to fit my needs. The API Gateway calls a Lambda function that writes to a DynamoDB table.
I am able to make a websocket connection but when I make my next request to insert some data the data appears successfully in my DynamoDB table but the response I get back is Internal Server Error.
I don't understand what is causing the Internal Server Error. When I look in the CloudWatch logs I just see normal traffic with no errors.
I could use some help understanding what is going wrong or how I can troubleshoot this better.
Here is the Lamba function that is being called:
const AWS = require("aws-sdk");
const customId = require("custom-id");
const ddb = new AWS.DynamoDB.DocumentClient({
apiVersion: "2012-08-10",
region: process.env.AWS_REGION,
});
exports.handler = async (event) => {
const uniqueId = customId({
randomLength: 1,
});
const data = {
uniqueId: uniqueId,
members: [
{
connectionId: event.requestContext.connectionId,
},
],
events: [],
parameters: [],
};
const putParams = {
TableName: process.env.EVENT_TABLE_NAME,
Item: data,
};
try {
await ddb.put(putParams).promise();
} catch (err) {
return {
statusCode: 400,
body: "Failed to create: " + JSON.stringify(err),
};
}
return { statusCode: 200, body: putParams };
};
Image of AWS CloudWatch Logs
The error returned by wcat looks like this:
{"message": "Internal server error", "connectionId":"NZxV_ddNIAMCJrw=", "requestId":"NZxafGiyoAMFoAA="}
I just had the same problem. The issue in my case was because API Gateway did not have permission to call the Lambda function in order to process a message arriving from the websocket. The 'internal server error' in this case is API Gateway saying it had some problem when it tried to invoke the Lambda function to handle the websocket message.
I was using CDK to deploy the infrastructure, and I created one WebSocketLambdaIntegration for the connect, disconnect and default websocket handlers, but this doesn't work. You have to create separate WebSocketLambdaIntegration instances even if you are calling the same Lambda function for all websocket events, otherwise CDK does not set the correct permissions.
I could see this was the problem because 1) I was using the same Lambda function for the connect, disconnect and default routes, and 2) in CloudWatch Logs I was only seeing log messages for one of these routes, in this case the 'connect' one. When I sent a message over the websocket, I was not seeing the expected log messages from the Lambda that was supposed to be handling incoming websocket messages. When I disconnected from the websocket, I did not see the expected log messages from the 'disconnect' handler.
This was because CDK had only given Lambda invoke permission to specific routes on the API Gateway websocket stage, and it had only authorised the 'connect' route, not the others.
Fixing the CDK stack so that it correctly assigned permissions, allowing API Gateway to invoke my Lambda for all websocket routes, fixed the problem.
I see it now. It was the last line. I changed it and now it works fine.
return { statusCode: 200, body: JSON.stringify(putParams) };
I am using a Slack webhook to process incoming SMS messages from Twilio. However, the way I have it set up, It seems that Twilio is expecting the web server (slack) to respond to it. This causes errors to be generated in Twilio, and I obviously don't want errors because I'll be getting emails.
I am using the twilio-ruby gem in Ruby to send out the SMS messages, and using the slack-ruby-client to monitor incoming messages from Slack.
How do I stop Twilio from trying to expect a response from the web server when it POSTS to the Slack webhook? Is that even possible or do I have this all configured incorrectly?
EDIT
Here's the function that I have which sends the forwarded SMS to Slack:
const https = require("https");
// Make sure to declare SLACK_WEBHOOK_PATH in your Environment
// variables at
// https://www.twilio.com/console/runtime/functions/configure
exports.handler = (context, event, callback) => {
// Extract the bits of the message we want
const { To, From, Body } = event;
// Construct a payload for slack's incoming webhooks
const slackBody = JSON.stringify({
text: `!asi SMS\nFrom: ${From}\nMessage: ${Body}`
});
// Form our request specification
const options = {
host: "hooks.slack.com",
port: 443,
path: context.SLACK_WEBHOOK_PATH,
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": slackBody.length
}
};
// send the request
const post = https.request(options, res => {
// only respond once we're done, or Twilio's functions
// may kill our execution before we finish.
res.on("end", () => {
// respond with an empty message
callback(null, new Twilio.twiml.MessagingResponse());
});
});
post.write(slackBody);
post.end();
};
Twilio developer evangelist here.
Twilio is always going to expect at least a 200 response or will timeout at 15 seconds for incoming message webhooks.
You could avoid the error messages by using something in between Twilio and Slack, like Zapier (example in this blog post) or using a Twilio Function (as described here) or with Twilio Studio (from the documentation here).
Hope one of those ideas helps!
Update
Further to my earlier answer, and given the code you used to make the call, I have an update.
When making a request using Node's built in https module you will not get the end event until you have read the data. This is what is causing the timeout between Twilio and the Twilio Function, you are never responding to it because you don't consume the data from the request.
In a quick test I found that just listening for the data event meant that the end event did fire. So update your function to:
const post = https.request(options, res => {
// only respond once we're done, or Twilio's functions
// may kill our execution before we finish.
res.on("data", () => {});
res.on("end", () => {
// respond with an empty message
callback(null, new Twilio.twiml.MessagingResponse());
});
});
And it should work.
Hi i am using azure process to send the push notification to windows 10
above version hybrid app and i use the below code to send the notification
https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-
mobile-cordova-get-started-push
i got this document there
pushRegistration.on('registration', function (data) {
this method is not firing is there any process to register before to send
notification
You have to implement a registerForPushNotifications method an call it every time user opens the App:
var pushRegistration = null;
function registerForPushNotifications() {
pushRegistration = PushNotification.init({
android: { senderID: 'Your_Project_ID' },
ios: { alert: 'true', badge: 'true', sound: 'true' },
wns: {}
});
If pushRegistration.on is not called, maybe registration is not complete or there is some error.
Create a breakpoint or print some message in:
pushRegistration.on('error', handleError);
And take a look if it's something wrong.
Also, you can check if there is some missing configuration following the Notification Hubs Diagnosis guidelines: https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-push-notification-fixer
My app has notifications based on zip code and channels.
When a user changes zip code the app updates the Installation with the new zip.
In my beforeSave on Installation I grab the new zip and subscribed channels and search for relevant notifications.
Then I need to send the notifications as pushes back to that installation.
Two questions:
Can I just push to the Installation object that came into the beforeSave as such:
return Parse.Push.send({
where: request.object
data: data
})
or do I have to do an Installation query for that objectId?
I can't just push the notification object. I need to configure the data. If there are multiple notifications (not likely but possible) what's the best way to send multiple pushes back to that installation (assuming I don't want to put them all in one push)?
I can't send the pushes from a for loop. Can I do something like this:
return notificationQuery.each().then( function(notification) {
//configure push from that notification
return Parse.Push.send ... etc
})
Thanks!
You can send Push notifications in parse based on channels or where(query) but not both.
So you can do a query on Installation class with channel and zipcode:
var query = new Parse.Query(Parse.Installation);
query.equalTo('channels', 'Indians');
query.equalTo('zipcode', "345678");
Parse.Push.send({
where: query,
data: {
action: "com.example.UPDATE_STATUS"
alert: "Ricky Vaughn was injured in last night's game!",
name: "Vaughn",
newsItem: "Man bites dog"
}
}, {
success: function() {
// Push was successful
},
error: function(error) {
// Handle error
}
});
Hope this helps.
Adding a content-available value to the payload parameter of the azure mobile services' apns send method doesn't seem to have any effect.
Is that the case ?
And if so, does that mean remote notifications (i.e. silent pushes) aren't possible via azure mobile services ?
Here's how i'm trying:
exports.post = function(request, response) {
var push = request.service.push;
push.apns.send('token', {
'content-available': 1,
sound: 0
// priority: 5,
// alert: 'value',
// badge: 1,
// sound: 'default',
// payload: {
// ...
//}
});
};
This should be working for you. Please review the following link for more information to ensure you've also configured your application to receive a silent notification.
http://hayageek.com/ios-silent-push-notifications/