Mobile Device Detection and Redirection in Node and Express
Join the DZone community and get the full member experience.
Join For FreeOne of the challenges of writing a mobile web site is what to do if a user hits the site from a desktop. Of course, some will say that you should simply make the site responsive, able to look good regardless of the browser it is displayed on. But what if the site is a game? I know all of the responsive design true believers will be upset with my solution, but so what, I like it. I "iframe" the mobile site into a 320 x 480 window on the desktop page. This brings up more challenges, like how detect a mobile device and how to route to the correct page?
The first challenge has already been solved by the excellent web site: http://detectmobilebrowsers.com/. They have created a rather long regular expression which detects a mobile browser by its user agent. The answer to the second challenge comes from the Express.js middleware which makes Node.js a great framework.
Express allows the developer to inject middleware into the route handler. For our root route we will call the checkForMobile method. If we detect a mobile browser, we will redirect to our mobile route. On all other routes, we won't bother checking for mobile. If a desktop user wishes to navigate directly to the mobile page, we will let them.
Please check out the code sample below to see how it is done. Or, if you are interested in the complete, and still in progress, mobile game, check it out at: https://github.com/Rockncoder/planegame. To see the live and very much in progress code, go to: http://planegame.herokuapp.com/
/** * Module dependencies. */ var express = require('express') , routes = require('./routes') , http = require('http') , hbs = require('hbs') , path = require('path') , app = express(); app.configure(function () { app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'hbs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); }); app.configure('development', function () { app.use(express.errorHandler()); }); // when the root route is called, do our mobile check app.get('/', checkForMobile, routes.desktop); app.get('/mobile', routes.mobile); http.createServer(app).listen(app.get('port'), function () { console.log("Express server listening on port " + app.get('port')); }); // returns true if the caller is a mobile phone (not tablet) // compares the user agent of the caller against a regex // This regex comes from http://detectmobilebrowsers.com/ function isCallerMobile(req) { var ua = req.headers['user-agent'].toLowerCase(), isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4)); return !!isMobile; } // note: the next method param is passed as well function checkForMobile(req, res, next) { // check to see if the caller is a mobile device var isMobile = isCallerMobile(req); if (isMobile) { console.log("Going mobile"); res.redirect('/mobile'); } else { // if we didn't detect mobile, call the next method, which will eventually call the desktop route return next(); } }
Published at DZone with permission of Troy Miles, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Redefining DevOps: The Transformative Power of Containerization
-
Build a Simple Chat Server With gRPC in .Net Core
-
What Is Test Pyramid: Getting Started With Test Automation Pyramid
-
Why You Should Consider Using React Router V6: An Overview of Changes
Comments