UNPKG

2.33 kBJavaScriptView Raw
1'use strict';
2
3const ipRegex = require('ip-regex');
4const micromatch = require('micromatch');
5const toPath = require('to-file-path');
6
7/**
8 * Filter `ip` against glob `patterns`, using [micromatch][] under the hood,
9 * so `options` are passed to it.
10 *
11 * @example
12 * const ipFilter = require('ip-filter');
13 *
14 * console.log(ipFilter('123.77.34.89', '123.??.34.8*')); // => '123.77.34.89'
15 * console.log(ipFilter('123.222.34.88', '123.??.34.8*')); // => null
16 * console.log(ipFilter('123.222.33.1', ['123.*.34.*', '*.222.33.*'])); // => '123.222.33.1'
17 *
18 * // should notice the difference
19 * console.log(ipFilter('123.222.34.88', ['123.*.34.*', '!123.222.**']));
20 * // => null
21 * console.log(ipFilter('123.222.34.88', ['123.*.34.*', '!123.222.*']));
22 * // => '123.222.34.88'
23 *
24 * @example
25 * const ipFilter = require('ip-filter');
26 * //
27 * // NON-STRICT mode
28 * //
29 *
30 * const res = ipFilter('x-koaip', ['*-koaip', '!foo-koa*'], { strict: false });
31 * console.log(res); // => 'x-koaip'
32 *
33 * const res = ipFilter('x-koa.foo', ['*-koa.*', '!foo-koa.*'], { strict: false });
34 * console.log(res); // => 'x-koa.foo'
35 *
36 * @name ipFilter
37 * @param {string} `ip` Accepts only valid IPs by default
38 * @param {string|array} `patterns` Basically everything that [micromatch][]'s second argument can accept.
39 * @param {object} `options` Pass `strict: false` if want to validate non-ip values,
40 * options are also passed to [micromatch][].
41 * @return {string} a `string` or `null` - If not match returns `null`, otherwise the passed `ip` as string.
42 * @api public
43 */
44module.exports = function ipFilter(ip, patterns, options) {
45 if (typeof ip !== 'string') {
46 throw new TypeError('ip-filter: expect `ip` to be a string');
47 }
48
49 const opts = { ...options };
50 opts.strict = typeof opts.strict === 'boolean' ? opts.strict : true;
51
52 if (opts.strict && !ipRegex().test(ip)) {
53 throw new Error('ip-filter: expect only valid IPs when `opts.strict` mode');
54 }
55
56 const id = opts.strict ? tofp(ip) : ip;
57 const globs = opts.strict ? tofp(patterns) : patterns;
58
59 const matches = micromatch(id, globs, opts);
60 return matches.length > 0 ? ip : null;
61};
62
63function tofp(val) {
64 const value = typeof val === 'string' ? toPath(val) : val;
65 return Array.isArray(value) ? value.map((p) => toPath(p)) : value;
66}