Skip to content

Instantly share code, notes, and snippets.

@ixisio
Last active August 29, 2015 13:56
Show Gist options
  • Save ixisio/9205231 to your computer and use it in GitHub Desktop.
Save ixisio/9205231 to your computer and use it in GitHub Desktop.
[DRAFT] A RESS Server implementation for Node.js

A RESS-Server Implementation with Node.js

RESS [ˈrəs] - RWD And Server-Side Components

How often you write a waste condition or another piece of code in your responsive frontend project, based on different viewports or different browser capabilities. That would be totally obsolet, if the server has some more information about the device to which it delivers. At this time, RESS comes into the game.

This document is the result of my research for already existing RESS implementation written in Node.js.

Background and objectives

I'm not a fan of DDRs (Device Description Repositorys) like WURFL, but today it seems to be the only consistent solution of server-side feature / device detection.

Another promising way to grab some information from the client-side are HTPP Client-Hints, coined by Ilya Grigorik.

HTTP Client Hints can be used as input to proactive content negotiation; just as the Accept header allowed clients to indicate what formats they prefer, Client Hints allow clients to indicate a list of device and agent specific preferences.

I would appreciate to see CHs landing in all modern browsers. Good stuff already happening: Blink: Intent to Implement: Client-Hints header (DPR switching)


So, I assume that server-side feature detection is not possible at the moment, without hacking cookie or redirect based techniques (Detector).

I do NOT want to use:

  • .. a DDR / device database
  • .. a cookie/session based technique
  • .. a client-side javascript solution, in which the client is polling for specific content. (e.g picturefill.js)

Server-side detection of, what?

@todo

  • Features (with caniuse!?)
  • Device Category ?? We should really need this? Why?
  • Viewport properties (e.g size, orientation)
  • Context information (e.g current bandwidth, inMotion, ..)

Proposal

@todo

  1. User-Agent detection (req.headers['user-agent'])
  2. UA parsing
  3. Extract device and browser identifiers {name:'android', version: '2.3', device: 'GT-I9100'}
  4. [and assigment to a device-class (e.g mobile, mobile-, desktop) ] Device Classification
  5. Get latest data from Can I use support tables caniuse-db

Inspiration & Benchmarks

// from https://github.com/rguerreiro/express-device
function DeviceParser(req, options) {
var self = this;
self.user_agent = function () {
return req.headers['user-agent'];
};
self.get_type = function () {
var ua = self.user_agent();
if (!ua || ua === '') {
// No user agent.
return 'u';
}
if (ua.match(/GoogleTV|SmartTV|Internet TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\-HTML/i)) {
// if user agent is a smart TV - http://goo.gl/FocDk
return 'tv';
} else if (ua.match(/Xbox|PLAYSTATION 3|Wii/i)) {
// if user agent is a TV Based Gaming Console
return 'tv';
} else if (ua.match(/iP(a|ro)d/i) || (ua.match(/tablet/i) && !ua.match(/RX-34/i)) || ua.match(/FOLIO/i)) {
// if user agent is a Tablet
return 'tablet';
} else if (ua.match(/Linux/i) && ua.match(/Android/i) && !ua.match(/Fennec|mobi|HTC Magic|HTCX06HT|Nexus One|SC-02B|fone 945/i)) {
// if user agent is an Android Tablet
return 'tablet';
} else if (ua.match(/Kindle/i) || (ua.match(/Mac OS/i) && ua.match(/Silk/i)) || (ua.match(/AppleWebKit/i) && ua.match(/Silk/i) && !ua.match(/Playstation Vita/i))) {
// if user agent is a Kindle or Kindle Fire
return 'tablet';
} else if (ua.match(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC( Flyer|_Flyer)|Sprint ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos S7|Dell Streak 7|Advent Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || (ua.match(/MB511/i) && ua.match(/RUTEM/i))) {
// if user agent is a pre Android 3.0 Tablet
return 'tablet';
} else if (ua.match(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google Wireless Transcoder/i)) {
// if user agent is unique phone User Agent
return 'phone';
} else if (ua.match(/Opera/i) && ua.match(/Windows NT 5/i) && ua.match(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i)) {
// if user agent is an odd Opera User Agent - http://goo.gl/nK90K
return 'phone';
} else if ((ua.match(/Windows (NT|XP|ME|9)/) && !ua.match(/Phone/i)) && !ua.match(/Bot|Spider|ia_archiver|NewsGator/i) || ua.match(/Win( ?9|NT)/i)) {
// if user agent is Windows Desktop
return 'desktop';
} else if (ua.match(/Macintosh|PowerPC/i) && !ua.match(/Silk/i)) {
// if agent is Mac Desktop
return 'desktop';
} else if (ua.match(/Linux/i) && ua.match(/X11/i) && !ua.match(/Charlotte/i)) {
// if user agent is a Linux Desktop
return 'desktop';
} else if (ua.match(/CrOS/)) {
// if user agent is a Chrome Book
return 'desktop';
} else if (ua.match(/Solaris|SunOS|BSD/i)) {
// if user agent is a Solaris, SunOS, BSD Desktop
return 'desktop';
} else if (ua.match(/curl|Bot|B-O-T|Crawler|Spider|Spyder|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|Charlotte|NewsGator|TinEye|Cerberian|SearchSight|Zao|Scrubby|Qseero|PycURL|Pompos|oegp|SBIder|yoogliFetchAgent|yacy|webcollage|VYU2|voyager|updated|truwoGPS|StackRambler|Sqworm|silk|semanticdiscovery|ScoutJet|Nymesis|NetResearchServer|MVAClient|mogimogi|Mnogosearch|Arachmo|Accoona|holmes|htdig|ichiro|webis|LinkWalker|lwp-trivial|facebookexternalhit/i) && !ua.match(/phone|Playstation/i)) {
// if user agent is a BOT/Crawler/Spider
return 'bot';
} else {
// Otherwise assume it is a phone Device
return 'u';
}
};
}
exports.Parser = DeviceParser;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment