mirror of
https://github.com/faisalman/ua-parser-js.git
synced 2025-09-27 07:58:45 +03:00
Add new feature: ability to pass req.headers object directly into UAParser
This commit is contained in:
parent
9ee128ae2b
commit
d99ff741f4
11
readme.md
11
readme.md
@ -53,7 +53,7 @@ Usually you can find the user agent in:
|
|||||||
## Constructor
|
## Constructor
|
||||||
When you call `UAParser` with the `new` keyword `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string.
|
When you call `UAParser` with the `new` keyword `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string.
|
||||||
Like so:
|
Like so:
|
||||||
* `new UAParser([user-agent:string][,extensions:object])`
|
* `new UAParser([user-agent:string][,extensions:object][,headers:object(since@1.1)])`
|
||||||
```js
|
```js
|
||||||
let parser = new UAParser("user-agent"); // you need to pass the user-agent for nodejs
|
let parser = new UAParser("user-agent"); // you need to pass the user-agent for nodejs
|
||||||
console.log(parser); // {}
|
console.log(parser); // {}
|
||||||
@ -70,7 +70,7 @@ console.log(parserResults);
|
|||||||
```
|
```
|
||||||
|
|
||||||
When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
|
When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results.
|
||||||
* `UAParser([user-agent:string][,extensions:object])`
|
* `UAParser([user-agent:string][,extensions:object][,headers:object(since@1.1)])`
|
||||||
* returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
|
* returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }`
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
@ -293,16 +293,17 @@ engine.toString(); // "Blink 28.0.1500.95"
|
|||||||
|
|
||||||
If you want to detect something that's not currently provided by UAParser.js (eg: bots, specific apps, etc), you can pass a list of regexes to extend internal UAParser.js regexes with your own.
|
If you want to detect something that's not currently provided by UAParser.js (eg: bots, specific apps, etc), you can pass a list of regexes to extend internal UAParser.js regexes with your own.
|
||||||
|
|
||||||
* `UAParser([uastring,] extensions)`
|
* `UAParser([uastring,] extensions [,headers:object(since@1.1)])`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Example:
|
// Example:
|
||||||
let myOwnListOfBrowsers = [
|
let myOwnListOfBrowsers = [
|
||||||
[/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION]
|
[/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']]
|
||||||
];
|
];
|
||||||
let myParser = new UAParser({ browser: myOwnListOfBrowsers });
|
let myParser = new UAParser({ browser: myOwnListOfBrowsers });
|
||||||
let myUA = 'Mozilla/5.0 MyBrowser/1.3';
|
let myUA = 'Mozilla/5.0 MyBrowser/1.3';
|
||||||
console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3"}
|
console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3", major: "1", type : "bot"}
|
||||||
|
console.log(myParser.getBrowser().is('bot')); // true
|
||||||
|
|
||||||
// Another example:
|
// Another example:
|
||||||
let myOwnListOfDevices = [
|
let myOwnListOfDevices = [
|
||||||
|
131
src/ua-parser.js
131
src/ua-parser.js
@ -37,6 +37,7 @@
|
|||||||
SMARTTV = 'smarttv',
|
SMARTTV = 'smarttv',
|
||||||
WEARABLE = 'wearable',
|
WEARABLE = 'wearable',
|
||||||
EMBEDDED = 'embedded',
|
EMBEDDED = 'embedded',
|
||||||
|
USER_AGENT = 'user-agent',
|
||||||
UA_MAX_LENGTH = 350;
|
UA_MAX_LENGTH = 350;
|
||||||
|
|
||||||
var AMAZON = 'Amazon',
|
var AMAZON = 'Amazon',
|
||||||
@ -71,11 +72,7 @@
|
|||||||
var extend = function (regexes, extensions) {
|
var extend = function (regexes, extensions) {
|
||||||
var mergedRegexes = {};
|
var mergedRegexes = {};
|
||||||
for (var i in regexes) {
|
for (var i in regexes) {
|
||||||
if (extensions[i] && extensions[i].length % 2 === 0) {
|
mergedRegexes[i] = extensions[i] && extensions[i].length % 2 === 0 ? extensions[i].concat(regexes[i]) : regexes[i];
|
||||||
mergedRegexes[i] = extensions[i].concat(regexes[i]);
|
|
||||||
} else {
|
|
||||||
mergedRegexes[i] = regexes[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return mergedRegexes;
|
return mergedRegexes;
|
||||||
},
|
},
|
||||||
@ -89,6 +86,11 @@
|
|||||||
has = function (str1, str2) {
|
has = function (str1, str2) {
|
||||||
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
||||||
},
|
},
|
||||||
|
isExtensions = function (obj) {
|
||||||
|
for (var prop in obj) {
|
||||||
|
return /^(browser|cpu|device|engine|os)$/.test(prop);
|
||||||
|
}
|
||||||
|
},
|
||||||
lowerize = function (str, rgx) {
|
lowerize = function (str, rgx) {
|
||||||
return typeof(str) === STR_TYPE ? str.toLowerCase().replace((rgx ? new RegExp(rgx, 'i') : EMPTY), EMPTY) : str;
|
return typeof(str) === STR_TYPE ? str.toLowerCase().replace((rgx ? new RegExp(rgx, 'i') : EMPTY), EMPTY) : str;
|
||||||
},
|
},
|
||||||
@ -803,84 +805,83 @@
|
|||||||
return callback(this.data);
|
return callback(this.data);
|
||||||
};
|
};
|
||||||
UAItem.createUAData = function (data) {
|
UAItem.createUAData = function (data) {
|
||||||
return (function () {
|
var is_ignoreProps = data.is_ignoreProps,
|
||||||
var propIs = data.propIs;
|
is_ignoreRgx = data.is_ignoreRgx,
|
||||||
var ignoreIs = data.ignoreIs;
|
toString_props = data.toString_props;
|
||||||
var propToStr = data.propToStr;
|
|
||||||
var UAData = function () {
|
var UAData = function () {
|
||||||
for (var i in data.props) {
|
for (var i in data.init_props) {
|
||||||
this[data.props[i]] = undefined;
|
this[data.init_props[i]] = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
UAData.prototype.is = function (strToCheck) {
|
||||||
|
var is = false;
|
||||||
|
for (var i in this) {
|
||||||
|
if (this.hasOwnProperty(i) && !is_ignoreProps[i] && lowerize(this[i], is_ignoreRgx) === lowerize(strToCheck, is_ignoreRgx)) {
|
||||||
|
is = true;
|
||||||
|
if (strToCheck != UNDEF_TYPE) break;
|
||||||
|
} else if (strToCheck == UNDEF_TYPE && is) {
|
||||||
|
is = !is;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
UAData.prototype.is = function (strToCheck) {
|
return is;
|
||||||
var is = false;
|
};
|
||||||
for (var i in propIs) {
|
UAData.prototype.toString = function () {
|
||||||
if (lowerize(this[propIs[i]], ignoreIs) === lowerize(strToCheck, ignoreIs)) {
|
var str = EMPTY;
|
||||||
is = true;
|
for (var i in toString_props) {
|
||||||
if (strToCheck != UNDEF_TYPE) break;
|
if (typeof(this[toString_props[i]]) !== UNDEF_TYPE) {
|
||||||
} else if (strToCheck == UNDEF_TYPE && is) {
|
str += (str ? ' ' : EMPTY) + this[toString_props[i]];
|
||||||
is = !is;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return is;
|
}
|
||||||
};
|
return str ? str : UNDEF_TYPE;
|
||||||
UAData.prototype.toString = function () {
|
};
|
||||||
var str = EMPTY;
|
return new UAData();
|
||||||
for (var i in propToStr) {
|
|
||||||
if (typeof(this[propToStr[i]]) !== UNDEF_TYPE) {
|
|
||||||
str += (str ? ' ' : EMPTY) + this[propToStr[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str ? str : UNDEF_TYPE;
|
|
||||||
};
|
|
||||||
return new UAData();
|
|
||||||
})(data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function UABrowser () {
|
function UABrowser () {
|
||||||
this.data = UAItem.createUAData({
|
this.data = UAItem.createUAData({
|
||||||
props : [NAME, VERSION, MAJOR],
|
init_props : [NAME, VERSION, MAJOR],
|
||||||
propIs : [NAME],
|
is_ignoreProps : [VERSION, MAJOR],
|
||||||
ignoreIs : ' ?browser$',
|
is_ignoreRgx : ' ?browser$',
|
||||||
propToStr : [NAME, VERSION]
|
toString_props : [NAME, VERSION]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
UABrowser.prototype = new UAItem();
|
UABrowser.prototype = new UAItem();
|
||||||
|
|
||||||
function UACPU () {
|
function UACPU () {
|
||||||
this.data = UAItem.createUAData({
|
this.data = UAItem.createUAData({
|
||||||
props : [ARCHITECTURE],
|
init_props : [ARCHITECTURE],
|
||||||
propIs : [ARCHITECTURE],
|
is_ignoreProps : [],
|
||||||
propToStr : [ARCHITECTURE]
|
toString_props : [ARCHITECTURE]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
UACPU.prototype = new UAItem();
|
UACPU.prototype = new UAItem();
|
||||||
|
|
||||||
function UADevice () {
|
function UADevice () {
|
||||||
this.data = UAItem.createUAData({
|
this.data = UAItem.createUAData({
|
||||||
props : [TYPE, MODEL, VENDOR],
|
init_props : [TYPE, MODEL, VENDOR],
|
||||||
propIs : [TYPE, MODEL, VENDOR],
|
is_ignoreProps : [],
|
||||||
propToStr : [VENDOR, MODEL]
|
toString_props : [VENDOR, MODEL]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
UADevice.prototype = new UAItem();
|
UADevice.prototype = new UAItem();
|
||||||
|
|
||||||
function UAEngine () {
|
function UAEngine () {
|
||||||
this.data = UAItem.createUAData({
|
this.data = UAItem.createUAData({
|
||||||
props : [NAME, VERSION],
|
init_props : [NAME, VERSION],
|
||||||
propIs : [NAME],
|
is_ignoreProps : [VERSION],
|
||||||
propToStr : [NAME, VERSION]
|
toString_props : [NAME, VERSION]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
UAEngine.prototype = new UAItem();
|
UAEngine.prototype = new UAItem();
|
||||||
|
|
||||||
function UAOS () {
|
function UAOS () {
|
||||||
this.data = UAItem.createUAData({
|
this.data = UAItem.createUAData({
|
||||||
props : [NAME, VERSION],
|
init_props : [NAME, VERSION],
|
||||||
propIs : [NAME],
|
is_ignoreProps : [VERSION],
|
||||||
ignoreIs : ' ?os$',
|
is_ignoreRgx : ' ?os$',
|
||||||
propToStr : [NAME, VERSION]
|
toString_props : [NAME, VERSION]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
UAOS.prototype = new UAItem();
|
UAOS.prototype = new UAItem();
|
||||||
@ -897,18 +898,30 @@
|
|||||||
}
|
}
|
||||||
UAResult.prototype = new UAItem();
|
UAResult.prototype = new UAItem();
|
||||||
|
|
||||||
function UAParser (ua, extensions) {
|
function UAParser (ua, extensions, headers) {
|
||||||
|
|
||||||
if (typeof ua === OBJ_TYPE) {
|
if (typeof ua === OBJ_TYPE) {
|
||||||
extensions = ua;
|
if (isExtensions(ua)) {
|
||||||
|
if (typeof extensions === OBJ_TYPE) {
|
||||||
|
headers = extensions; // case UAParser(extensions, headers)
|
||||||
|
}
|
||||||
|
extensions = ua; // case UAParser(extensions)
|
||||||
|
} else {
|
||||||
|
headers = ua; // case UAParser(headers)
|
||||||
|
}
|
||||||
ua = undefined;
|
ua = undefined;
|
||||||
}
|
} else if (typeof ua === STR_TYPE && !isExtensions(extensions)) {
|
||||||
if (!(this instanceof UAParser)) {
|
headers = extensions; // case UAParser(ua, headers)
|
||||||
return new UAParser(ua, extensions).getResult();
|
extensions = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(this instanceof UAParser)) {
|
||||||
|
return new UAParser(ua, extensions, headers).getResult();
|
||||||
|
}
|
||||||
var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;
|
var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;
|
||||||
var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : EMPTY);
|
|
||||||
|
// _ua = user-supplied string || window.navigator.userAgent || user-agent header || empty
|
||||||
|
var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : (!ua && headers && headers[USER_AGENT] ? headers[USER_AGENT] : EMPTY));
|
||||||
var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;
|
var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;
|
||||||
var _rgxmap = extensions ? extend(regexes, extensions) : regexes;
|
var _rgxmap = extensions ? extend(regexes, extensions) : regexes;
|
||||||
|
|
||||||
|
100
test/test.js
100
test/test.js
@ -106,6 +106,25 @@ describe('Extending Regex', function () {
|
|||||||
parser2.setUA(uaString);
|
parser2.setUA(uaString);
|
||||||
assert.strictEqual(parser2.getBrowser().name, 'MyOwnBrowser');
|
assert.strictEqual(parser2.getBrowser().name, 'MyOwnBrowser');
|
||||||
assert.strictEqual(parser1.getBrowser().version, '1.3');
|
assert.strictEqual(parser1.getBrowser().version, '1.3');
|
||||||
|
|
||||||
|
let myOwnListOfBrowsers = [
|
||||||
|
[/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION, ['type', 'bot']]
|
||||||
|
];
|
||||||
|
let myParser = new UAParser({ browser: myOwnListOfBrowsers });
|
||||||
|
let myUA = 'Mozilla/5.0 MyBrowser/1.3';
|
||||||
|
assert.deepEqual(myParser.setUA(myUA).getBrowser(), {name: "MyBrowser", version: "1.3", major: "1", type : "bot"});
|
||||||
|
assert.strictEqual(myParser.getBrowser().is('bot'), true);
|
||||||
|
|
||||||
|
let myOwnListOfDevices = [
|
||||||
|
[/(mytab) ([\w ]+)/i], [UAParser.DEVICE.VENDOR, UAParser.DEVICE.MODEL, [UAParser.DEVICE.TYPE, UAParser.DEVICE.TABLET]],
|
||||||
|
[/(myphone)/i], [UAParser.DEVICE.VENDOR, [UAParser.DEVICE.TYPE, UAParser.DEVICE.MOBILE]]
|
||||||
|
];
|
||||||
|
let myParser2 = new UAParser({
|
||||||
|
browser: myOwnListOfBrowsers,
|
||||||
|
device: myOwnListOfDevices
|
||||||
|
});
|
||||||
|
let myUA2 = 'Mozilla/5.0 MyTab 14 Pro Max';
|
||||||
|
assert.deepEqual(myParser2.setUA(myUA2).getDevice(), {vendor: "MyTab", model: "14 Pro Max", type: "tablet"});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('User-agent length', function () {
|
describe('User-agent length', function () {
|
||||||
@ -248,25 +267,72 @@ describe('is() utility method', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('toString() utility method', function () {
|
describe('toString() utility method', function () {
|
||||||
let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');
|
it('Should return full name', function () {
|
||||||
assert.strictEqual(uap.getBrowser().name, "IEMobile");
|
let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537');
|
||||||
assert.strictEqual(uap.getBrowser().version, "11.0");
|
assert.strictEqual(uap.getBrowser().name, "IEMobile");
|
||||||
assert.strictEqual(uap.getBrowser().major, "11");
|
assert.strictEqual(uap.getBrowser().version, "11.0");
|
||||||
assert.strictEqual(uap.getBrowser().toString(), "IEMobile 11.0");
|
assert.strictEqual(uap.getBrowser().major, "11");
|
||||||
|
assert.strictEqual(uap.getBrowser().toString(), "IEMobile 11.0");
|
||||||
|
|
||||||
assert.strictEqual(uap.getCPU().architecture, "arm");
|
assert.strictEqual(uap.getCPU().architecture, "arm");
|
||||||
assert.strictEqual(uap.getCPU().toString(), "arm");
|
assert.strictEqual(uap.getCPU().toString(), "arm");
|
||||||
|
|
||||||
assert.strictEqual(uap.getDevice().vendor, "Nokia");
|
assert.strictEqual(uap.getDevice().vendor, "Nokia");
|
||||||
assert.strictEqual(uap.getDevice().model, "Lumia 635");
|
assert.strictEqual(uap.getDevice().model, "Lumia 635");
|
||||||
assert.strictEqual(uap.getDevice().type, "mobile");
|
assert.strictEqual(uap.getDevice().type, "mobile");
|
||||||
assert.strictEqual(uap.getDevice().toString(), "Nokia Lumia 635");
|
assert.strictEqual(uap.getDevice().toString(), "Nokia Lumia 635");
|
||||||
|
|
||||||
assert.strictEqual(uap.getEngine().name, "Trident");
|
assert.strictEqual(uap.getEngine().name, "Trident");
|
||||||
assert.strictEqual(uap.getEngine().version, "7.0");
|
assert.strictEqual(uap.getEngine().version, "7.0");
|
||||||
assert.strictEqual(uap.getEngine().toString(), "Trident 7.0");
|
assert.strictEqual(uap.getEngine().toString(), "Trident 7.0");
|
||||||
|
|
||||||
assert.strictEqual(uap.getOS().name, "Windows Phone");
|
assert.strictEqual(uap.getOS().name, "Windows Phone");
|
||||||
assert.strictEqual(uap.getOS().version, "8.1");
|
assert.strictEqual(uap.getOS().version, "8.1");
|
||||||
assert.strictEqual(uap.getOS().toString(), "Windows Phone 8.1");
|
assert.strictEqual(uap.getOS().toString(), "Windows Phone 8.1");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Read user-agent data from req.headers', function () {
|
||||||
|
const ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)';
|
||||||
|
const ext = {
|
||||||
|
engine : [
|
||||||
|
[/(msie)/i], [[UAParser.ENGINE.NAME, 'Custom Browser 1']],
|
||||||
|
[/(edge)/i], [[UAParser.ENGINE.NAME, 'Custom Browser 2']]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const req = {
|
||||||
|
headers : {
|
||||||
|
'user-agent' : 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
it('Can be called with UAParser(ua)', function () {
|
||||||
|
let engine = UAParser(ua).engine;
|
||||||
|
assert.strictEqual(engine.name, "Trident");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can be called with UAParser(ua, extensions)', function () {
|
||||||
|
let engine = UAParser(ua, ext).engine;
|
||||||
|
assert.strictEqual(engine.name, "Custom Browser 1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can be called with UAParser(ua, extensions, headers)', function () {
|
||||||
|
let engine = UAParser(ua, ext, req.headers).engine;
|
||||||
|
assert.strictEqual(engine.name, "Custom Browser 1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can be called with UAParser(ua, headers)', function () {
|
||||||
|
let engine = UAParser(ua, req.headers).engine;
|
||||||
|
assert.strictEqual(engine.name, "Trident");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can be called with UAParser(extensions, headers)', function () {
|
||||||
|
let engine = UAParser(ext, req.headers).engine;
|
||||||
|
assert.strictEqual(engine.name, "Custom Browser 2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can be called with UAParser(headers)', function () {
|
||||||
|
let engine = UAParser(req.headers).engine;
|
||||||
|
assert.strictEqual(engine.name, "EdgeHTML");
|
||||||
|
});
|
||||||
});
|
});
|
Loading…
x
Reference in New Issue
Block a user