1 | # useragent - high performance user agent parser for Node.js
|
2 |
|
3 | Useragent originated as port of [browserscope.org][browserscope]'s user agent
|
4 | parser project also known as ua-parser. Useragent allows you to parse user agent
|
5 | string with high accuracy by using hand tuned dedicated regular expressions for
|
6 | browser matching. This database is needed to ensure that every browser is
|
7 | correctly parsed as every browser vendor implements it's own user agent schema.
|
8 | This is why regular user agent parsers have major issues because they will
|
9 | most likely parse out the wrong browser name or confuse the render engine version
|
10 | with the actual version of the browser.
|
11 |
|
12 | ---
|
13 |
|
14 | ### Build status [![BuildStatus](https://secure.travis-ci.org/3rd-Eden/useragent.png?branch=master)](http://travis-ci.org/3rd-Eden/useragent)
|
15 |
|
16 | ---
|
17 |
|
18 | ### High performance
|
19 |
|
20 | The module has been developed with a benchmark driven approach. It has a
|
21 | pre-compiled library that contains all the Regular Expressions and uses deferred
|
22 | or on demand parsing for Operating System and device information. All this
|
23 | engineering effort has been worth it as [this benchmark shows][benchmark]:
|
24 |
|
25 | ```
|
26 | Starting the benchmark, parsing 62 useragent strings per run
|
27 |
|
28 | Executed benchmark against node module: "useragent"
|
29 | Count (61), Cycles (5), Elapsed (5.559), Hz (1141.3739447904327)
|
30 |
|
31 | Executed benchmark against node module: "useragent_parser"
|
32 | Count (29), Cycles (3), Elapsed (5.448), Hz (545.6817291171243)
|
33 |
|
34 | Executed benchmark against node module: "useragent-parser"
|
35 | Count (16), Cycles (4), Elapsed (5.48), Hz (304.5373431830105)
|
36 |
|
37 | Executed benchmark against node module: "ua-parser"
|
38 | Count (54), Cycles (3), Elapsed (5.512), Hz (1018.7561434659247)
|
39 |
|
40 | Module: "useragent" is the user agent fastest parser.
|
41 | ```
|
42 |
|
43 | ---
|
44 |
|
45 | ### Installation
|
46 |
|
47 | Installation is done using the Node Package Manager (NPM). If you don't have
|
48 | NPM installed on your system you can download it from
|
49 | [npmjs.org][npm]
|
50 |
|
51 | ```
|
52 | npm install useragent --save
|
53 | ```
|
54 |
|
55 | The `--save` flag tells NPM to automatically add it to your `package.json` file.
|
56 |
|
57 | ---
|
58 |
|
59 | ### API
|
60 |
|
61 |
|
62 | Include the `useragent` parser in you node.js application:
|
63 |
|
64 | ```js
|
65 | var useragent = require('useragent');
|
66 | ```
|
67 |
|
68 | The `useragent` library allows you do use the automatically installed RegExp
|
69 | library or you can fetch it live from the remote servers. So if you are
|
70 | paranoid and always want your RegExp library to be up to date to match with
|
71 | agent the widest range of `useragent` strings you can do:
|
72 |
|
73 | ```js
|
74 | var useragent = require('useragent');
|
75 | useragent(true);
|
76 | ```
|
77 |
|
78 | This will async load the database from the server and compile it to a proper
|
79 | JavaScript supported format. If it fails to compile or load it from the remote
|
80 | location it will just fall back silently to the shipped version. If you want to
|
81 | use this feature you need to add `yamlparser` and `request` to your package.json
|
82 |
|
83 | ```
|
84 | npm install yamlparser --save
|
85 | npm install request --save
|
86 | ```
|
87 |
|
88 | #### useragent.parse(useragent string[, js useragent]);
|
89 |
|
90 | This is the actual user agent parser, this is where all the magic is happening.
|
91 | The function accepts 2 arguments, both should be a `string`. The first argument
|
92 | should the user agent string that is known on the server from the
|
93 | `req.headers.useragent` header. The other argument is optional and should be
|
94 | the user agent string that you see in the browser, this can be send from the
|
95 | browser using a xhr request or something like this. This allows you detect if
|
96 | the user is browsing the web using the `Chrome Frame` extension.
|
97 |
|
98 | The parser returns a Agent instance, this allows you to output user agent
|
99 | information in different predefined formats. See the Agent section for more
|
100 | information.
|
101 |
|
102 | ```js
|
103 | var agent = useragent.parse(req.headers['user-agent']);
|
104 |
|
105 | // example for parsing both the useragent header and a optional js useragent
|
106 | var agent2 = useragent.parse(req.headers['user-agent'], req.query.jsuseragent);
|
107 | ```
|
108 |
|
109 | The parse method returns a `Agent` instance which contains all details about the
|
110 | user agent. See the Agent section of the API documentation for the available
|
111 | methods.
|
112 |
|
113 | #### useragent.lookup(useragent string[, js useragent]);
|
114 |
|
115 | This provides the same functionality as above, but it caches the user agent
|
116 | string and it's parsed result in memory to provide faster lookups in the
|
117 | future. This can be handy if you expect to parse a lot of user agent strings.
|
118 |
|
119 | It uses the same arguments as the `useragent.parse` method and returns exactly
|
120 | the same result, but it's just cached.
|
121 |
|
122 | ```js
|
123 | var agent = useragent.lookup(req.headers['user-agent']);
|
124 | ```
|
125 |
|
126 | And this is a serious performance improvement as shown in this benchmark:
|
127 |
|
128 | ```
|
129 | Executed benchmark against method: "useragent.parse"
|
130 | Count (49), Cycles (3), Elapsed (5.534), Hz (947.6844321931629)
|
131 |
|
132 | Executed benchmark against method: "useragent.lookup"
|
133 | Count (11758), Cycles (3), Elapsed (5.395), Hz (229352.03831239208)
|
134 | ```
|
135 |
|
136 | #### useragent.fromJSON(obj);
|
137 |
|
138 | Transforms the JSON representation of a `Agent` instance back in to a working
|
139 | `Agent` instance
|
140 |
|
141 | ```js
|
142 | var agent = useragent.parse(req.headers['user-agent'])
|
143 | , another = useragent.fromJSON(JSON.stringify(agent));
|
144 |
|
145 | console.log(agent == another);
|
146 | ```
|
147 |
|
148 | #### useragent.is(useragent string).browsername;
|
149 |
|
150 | This api provides you with a quick and dirty browser lookup. The underlying
|
151 | code is usually found on client side scripts so it's not the same quality as
|
152 | our `useragent.parse` method but it might be needed for legacy reasons.
|
153 |
|
154 | `useragent.is` returns a object with potential matched browser names
|
155 |
|
156 | ```js
|
157 | useragent.is(req.headers['user-agent']).firefox // true
|
158 | useragent.is(req.headers['user-agent']).safari // false
|
159 | var ua = useragent.is(req.headers['user-agent'])
|
160 |
|
161 | // the object
|
162 | {
|
163 | version: '3'
|
164 | webkit: false
|
165 | opera: false
|
166 | ie: false
|
167 | chrome: false
|
168 | safari: false
|
169 | mobile_safari: false
|
170 | firefox: true
|
171 | mozilla: true
|
172 | android: false
|
173 | }
|
174 | ```
|
175 |
|
176 | ---
|
177 |
|
178 | ### Agents, OperatingSystem and Device instances
|
179 |
|
180 | Most of the methods mentioned above return a Agent instance. The Agent exposes
|
181 | the parsed out information from the user agent strings. This allows us to
|
182 | extend the agent with more methods that do not necessarily need to be in the
|
183 | core agent instance, allowing us to expose a plugin interface for third party
|
184 | developers and at the same time create a uniform interface for all versioning.
|
185 |
|
186 | The Agent has the following property
|
187 |
|
188 | - `family` The browser family, or browser name, it defaults to Other.
|
189 | - `major` The major version number of the family, it defaults to 0.
|
190 | - `minor` The minor version number of the family, it defaults to 0.
|
191 | - `patch` The patch version number of the family, it defaults to 0.
|
192 |
|
193 | In addition to the properties mentioned above, it also has 2 special properties,
|
194 | which are:
|
195 |
|
196 | - `os` OperatingSystem instance
|
197 | - `device` Device instance
|
198 |
|
199 | When you access those 2 properties the agent will do on demand parsing of the
|
200 | Operating System or/and Device information.
|
201 |
|
202 | The OperatingSystem has the same properties as the Agent, for the Device we
|
203 | don't have any versioning information available, so only the `family` property is
|
204 | set there. If we cannot find the family, they will default to `Other`.
|
205 |
|
206 | The following methods are available:
|
207 |
|
208 | #### Agent.toAgent();
|
209 |
|
210 | Returns the family and version number concatinated in a nice human readable
|
211 | string.
|
212 |
|
213 | ```js
|
214 | var agent = useragent.parse(req.headers['user-agent']);
|
215 | agent.toAgent(); // 'Chrome 15.0.874'
|
216 | ```
|
217 |
|
218 | #### Agent.toString();
|
219 |
|
220 | Returns the results of the `Agent.toAgent()` but also adds the parsed operating
|
221 | system to the string in a human readable format.
|
222 |
|
223 | ```js
|
224 | var agent = useragent.parse(req.headers['user-agent']);
|
225 | agent.toString(); // 'Chrome 15.0.874 / Mac OS X 10.8.1'
|
226 |
|
227 | // as it's a to string method you can also concat it with another string
|
228 | 'your useragent is ' + agent;
|
229 | // 'your useragent is Chrome 15.0.874 / Mac OS X 10.8.1'
|
230 | ```
|
231 | #### Agent.toVersion();
|
232 |
|
233 | Returns the version of the browser in a human readable string.
|
234 |
|
235 | ```js
|
236 | var agent = useragent.parse(req.headers['user-agent']);
|
237 | agent.toVersion(); // '15.0.874'
|
238 | ```
|
239 |
|
240 | #### Agent.toJSON();
|
241 |
|
242 | Generates a JSON representation of the Agent. By using the `toJSON` method we
|
243 | automatically allow it to be stringified when supplying as to the
|
244 | `JSON.stringify` method.
|
245 |
|
246 | ```js
|
247 | var agent = useragent.parse(req.headers['user-agent']);
|
248 | agent.toJSON(); // returns an object
|
249 |
|
250 | JSON.stringify(agent);
|
251 | ```
|
252 |
|
253 | #### OperatingSystem.toString();
|
254 |
|
255 | Generates a stringified version of operating system;
|
256 |
|
257 | ```js
|
258 | var agent = useragent.parse(req.headers['user-agent']);
|
259 | agent.os.toString(); // 'Mac OSX 10.8.1'
|
260 | ```
|
261 |
|
262 | #### OperatingSystem.toVersion();
|
263 |
|
264 | Generates a stringified version of operating system's version;
|
265 |
|
266 | ```js
|
267 | var agent = useragent.parse(req.headers['user-agent']);
|
268 | agent.os.toVersion(); // '10.8.1'
|
269 | ```
|
270 |
|
271 | #### OperatingSystem.toJSON();
|
272 |
|
273 | Generates a JSON representation of the OperatingSystem. By using the `toJSON`
|
274 | method we automatically allow it to be stringified when supplying as to the
|
275 | `JSON.stringify` method.
|
276 |
|
277 | ```js
|
278 | var agent = useragent.parse(req.headers['user-agent']);
|
279 | agent.os.toJSON(); // returns an object
|
280 |
|
281 | JSON.stringify(agent.os);
|
282 | ```
|
283 |
|
284 | #### Device.toString();
|
285 |
|
286 | Generates a stringified version of device;
|
287 |
|
288 | ```js
|
289 | var agent = useragent.parse(req.headers['user-agent']);
|
290 | agent.device.toString(); // 'Asus A100'
|
291 | ```
|
292 |
|
293 | #### Device.toVersion();
|
294 |
|
295 | Generates a stringified version of device's version;
|
296 |
|
297 | ```js
|
298 | var agent = useragent.parse(req.headers['user-agent']);
|
299 | agent.device.toVersion(); // '' , no version found but could also be '0.0.0'
|
300 | ```
|
301 |
|
302 | #### Device.toJSON();
|
303 |
|
304 | Generates a JSON representation of the Device. By using the `toJSON` method we
|
305 | automatically allow it to be stringified when supplying as to the
|
306 | `JSON.stringify` method.
|
307 |
|
308 | ```js
|
309 | var agent = useragent.parse(req.headers['user-agent']);
|
310 | agent.device.toJSON(); // returns an object
|
311 |
|
312 | JSON.stringify(agent.device);
|
313 | ```
|
314 |
|
315 | ### Adding more features to the useragent
|
316 |
|
317 | As I wanted to keep the core of the user agent parser as clean and fast as
|
318 | possible I decided to move some of the initially planned features to a new
|
319 | `plugin` file.
|
320 |
|
321 | These extensions to the Agent prototype can be loaded by requiring the
|
322 | `useragent/features` file:
|
323 |
|
324 | ```js
|
325 | var useragent = require('useragent');
|
326 | require('useragent/features');
|
327 | ```
|
328 |
|
329 | The initial release introduces 1 new method, satisfies, which allows you to see
|
330 | if the version number of the browser satisfies a certain range. It uses the
|
331 | semver library to do all the range calculations but here is a small summary of
|
332 | the supported range styles:
|
333 |
|
334 | * `>1.2.3` Greater than a specific version.
|
335 | * `<1.2.3` Less than.
|
336 | * `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`.
|
337 | * `~1.2.3` := `>=1.2.3 <1.3.0`.
|
338 | * `~1.2` := `>=1.2.0 <2.0.0`.
|
339 | * `~1` := `>=1.0.0 <2.0.0`.
|
340 | * `1.2.x` := `>=1.2.0 <1.3.0`.
|
341 | * `1.x` := `>=1.0.0 <2.0.0`.
|
342 |
|
343 | As it requires the `semver` module to function you need to install it
|
344 | seperately:
|
345 |
|
346 | ```
|
347 | npm install semver --save
|
348 | ```
|
349 |
|
350 | #### Agent.satisfies('range style here');
|
351 |
|
352 | Check if the agent matches the supplied range.
|
353 |
|
354 | ```js
|
355 | var agent = useragent.parse(req.headers['user-agent']);
|
356 | agent.satisfies('15.x || >=19.5.0 || 25.0.0 - 17.2.3'); // true
|
357 | agent.satisfies('>16.12.0'); // false
|
358 | ```
|
359 | ---
|
360 |
|
361 | ### Migrations
|
362 |
|
363 | For small changes between version please review the [changelog][changelog].
|
364 |
|
365 | #### Upgrading from 1.10 to 2.0.0
|
366 |
|
367 | - `useragent.fromAgent` has been removed.
|
368 | - `agent.toJSON` now returns an Object, use `JSON.stringify(agent)` for the old
|
369 | behaviour.
|
370 | - `agent.os` is now an `OperatingSystem` instance with version numbers. If you
|
371 | still a string only representation do `agent.os.toString()`.
|
372 | - `semver` has been removed from the dependencies, so if you are using the
|
373 | `require('useragent/features')` you need to add it to your own dependencies
|
374 |
|
375 | #### Upgrading from 0.1.2 to 1.0.0
|
376 |
|
377 | - `useragent.browser(ua)` has been renamed to `useragent.is(ua)`.
|
378 | - `useragent.parser(ua, jsua)` has been renamed to `useragent.parse(ua, jsua)`.
|
379 | - `result.pretty()` has been renamed to `result.toAgent()`.
|
380 | - `result.V1` has been renamed to `result.major`.
|
381 | - `result.V2` has been renamed to `result.minor`.
|
382 | - `result.V3` has been renamed to `result.patch`.
|
383 | - `result.prettyOS()` has been removed.
|
384 | - `result.match` has been removed.
|
385 |
|
386 | ---
|
387 |
|
388 | ### License
|
389 |
|
390 | MIT
|
391 |
|
392 | [browserscope]: http://www.browserscope.org/
|
393 | [benchmark]: /3rd-Eden/useragent/blob/master/benchmark/run.js
|
394 | [changelog]: /3rd-Eden/useragent/blob/master/CHANGELOG.md
|
395 | [npm]: http://npmjs.org
|