Ask Learn
Preview
Please sign in to use this experience.
Sign inThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In my previous post, I showed how you can enable an Azure Mobile Apps client to add tags to a push notification registration using the installation ID available on the client. While fairly popular, my original post was only for a .NET backend mobile app, and I got lots of requests to show an equivalent was to do the same in a Node.js backend.
NOTE: I’m also keeping an eye on an issue that the team is working on to whitelist tags so that clients can supply a set of pre-defined safe tags during registration. When that finally gets done, I will blog about it as it should be a bit easier than this, and not require an additional round-trip to the backend to add tags.
I finally had a chance to create a similar custom API in a Node.js backend Mobile App, with the goal of being able to have an identical API call to the .NET backend, where the POST request looks like this:
POST https://todolist.azurewebsites.net/api/updatetags/f211a45f-6f6d-4189-b106-e534af999fff HTTP/1.1
Host: todolist.azurewebsites.net
Content-Type: application/json
ZUMO-API-VERSION: 2.0.0
Content-Length: 20
["test","broadcast"]
In the express.js app, the following POST method implementation defines a custom router that handles this request and adds tags to the given installation (remember that an installation is a push registration tagged with the client’s installation ID):
// Define a POST operation that updates installation tags.
router.post('/:id', function (request, response) {
// Get the notification hub used by the mobile app.
var push = request.azureMobile.push;
var installationId = request.params.id;
// Get the tags array from the request message.
var tags = request.body;
// Validate for and block any SID tags.
for (i = 0; i < tags.length; i++) {
if (tags[i].search("sid:") !== -1) {
response.status(403)
.send("You cannot set '" + tags[i] + "' as a tag.");
return;
}
}
// Define an update tags operation.
var updateOperation = [{
"op": "add",
"path": "/tags",
"value": tags.toString()
}];
// Update the installation to add the new tags.
push.patchInstallation(installationId, updateOperation, function(error, res){
if(error){
logger.error('An error occurred when adding tags', error);
response.status(error.statusCode).send(error.detail);
}
else{
response.status(200).send(tags);
}
});
});
Note that this code validates the client-supplied tags to make sure a user ID isn’t being supplied, to prevent a user from getting push data for another user.
Just for completeness, here’s also the GET method that returns tags for a given registration:
// Define GET operation that returns tags for an installation.
router.get('/:id', function (request, response) {
// Get the notification hub used by the mobile app.
var push = request.azureMobile.push;
var installationId = request.params.id;
push.getInstallation(installationId, function(error, installation, res){
if (error){
// Log the error and send an error response.
logger.error('An error occurred when retrieving installation', error);
response.status(error.statusCode).send(error.detail);
}
else{
// Return an array of current tags.
response.json(installation.tags);
}
});
});
In particular, I wanted to keep the parameterized routes that I had in the .NET backend mobile app. Because of this, I wasn’t able to use the nice convenient JSON-based pattern for defining custom APIs in the /api subfolder. Instead, I ended-up having to use an express.js Router object to define my parameterized routes. Because I did this in a separate file in the ./api subfolder, I needed to expose my router as a module, which I consumed in the main app. Here’s how my router module is defined, without all the function code from above:
var express = require('express'); // Create an express.js router for our custom API. var router = express.Router(); // Define a POST operation that updates installation tags. router.post('/:id', function (request, response) { … }); // Define GET operation that returns tags for an installation. router.get('/:id', function (request, response) { …
}); module.exports = router;
Then, in the app itself, I added this app.use()
reference to hook-up to the ./api/udatetags
route:
app.use(mobileApp);
// Add the router module on the custom API endpoint.
app.use('/api/updatetags', require('./api/UpdateTags.js'));
app.listen(process.env.PORT || 3000); // Listen for requests.
That’s all there is. I am planning on including this custom API and routing in the Node.js version of the quickstart completed project, which I hope to publish this week. Note that I’m not a Node.js guru, so if you have suggested improvements to my code, please let me know in the comments.
Cheers!
Please sign in to use this experience.
Sign in