Skip to content

Commit

Permalink
Merge pull request #245 from oschwald/greg/prefix-length
Browse files Browse the repository at this point in the history
Add method to get prefix length for record
  • Loading branch information
Dmitry Shirokov authored Jan 1, 2020
2 parents b245db3 + d70c112 commit 3623da3
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 56 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ const maxmind = require('maxmind');

maxmind.open('/path/to/GeoLite2-City.mmdb').then((lookup) => {
console.log(lookup.get('66.6.44.4'));

console.log(lookup.getWithPrefixLength('66.6.44.4'));
});

maxmind.open('/path/to/GeoOrg.mmdb').then((lookup) => {
console.log(lookup.get('66.6.44.4'));

console.log(lookup.getWithPrefixLength('66.6.44.4'));
});
```

Expand All @@ -36,6 +40,8 @@ import maxmind, { CityResponse } from 'maxmind';

const lookup = await maxmind.open<CityResponse>('/path/to/GeoLite2-City.mmdb');
console.log(lookup.get('66.6.44.4')); // inferred type maxmind.CityResponse

console.log(lookup.getWithPrefixLength('66.6.44.4')); // tuple with inferred type [maxmind.CityResponse|null, number]
```

### Sync API
Expand All @@ -47,6 +53,8 @@ import { Reader } from 'maxmind';
const buffer = fs.readFileSync('./db.mmdb');
const lookup = new Reader<CityResponse>(buffer);
const city = lookup.get('8.8.8.8');

const [city2, prefixLength] = lookup.getWithPrefixLength('66.6.44.4');
```

Supported response types:
Expand Down
107 changes: 107 additions & 0 deletions src/__test__/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,111 @@ describe('maxmind', () => {
});
});
});

describe('getWithPrefixLength', () => {
const decoderRecord = {
array: [1, 2, 3],
boolean: true,
bytes: Buffer.from([0, 0, 0, 42]),
double: 42.123456,
float: 1.100000023841858,
int32: -268435456,
map: {
mapX: {
arrayX: [7, 8, 9],
utf8_stringX: 'hello',
},
},
uint128: '1329227995784915872903807060280344576',
uint16: 0x64,
uint32: 268435456,
uint64: '1152921504606846976',
utf8_string: 'unicode! ☯ - ♫',
};
const tests = [
{
ip: '1.1.1.1',
dbFile: 'MaxMind-DB-test-ipv6-32.mmdb',
expectedPrefixLength: 8,
expectedRecord: null,
},
{
ip: '::1:ffff:ffff',
dbFile: 'MaxMind-DB-test-ipv6-24.mmdb',
expectedPrefixLength: 128,
expectedRecord: { ip: '::1:ffff:ffff' },
},
{
ip: '::2:0:1',
dbFile: 'MaxMind-DB-test-ipv6-24.mmdb',
expectedPrefixLength: 122,
expectedRecord: { ip: '::2:0:0' },
},
{
ip: '1.1.1.1',
dbFile: 'MaxMind-DB-test-ipv4-24.mmdb',
expectedPrefixLength: 32,
expectedRecord: { ip: '1.1.1.1' },
},
{
ip: '1.1.1.3',
dbFile: 'MaxMind-DB-test-ipv4-24.mmdb',
expectedPrefixLength: 31,
expectedRecord: { ip: '1.1.1.2' },
},
{
ip: '1.1.1.3',
dbFile: 'MaxMind-DB-test-decoder.mmdb',
expectedPrefixLength: 24,
expectedRecord: decoderRecord,
},
{
ip: '::ffff:1.1.1.128',
dbFile: 'MaxMind-DB-test-decoder.mmdb',
expectedPrefixLength: 120,
expectedRecord: decoderRecord,
},
{
ip: '::1.1.1.128',
dbFile: 'MaxMind-DB-test-decoder.mmdb',
expectedPrefixLength: 120,
expectedRecord: decoderRecord,
},
{
ip: '200.0.2.1',
dbFile: 'MaxMind-DB-no-ipv4-search-tree.mmdb',
expectedPrefixLength: 0,
expectedRecord: '::0/64',
},
{
ip: '::200.0.2.1',
dbFile: 'MaxMind-DB-no-ipv4-search-tree.mmdb',
expectedPrefixLength: 64,
expectedRecord: '::0/64',
},
{
ip: '0:0:0:0:ffff:ffff:ffff:ffff',
dbFile: 'MaxMind-DB-no-ipv4-search-tree.mmdb',
expectedPrefixLength: 64,
expectedRecord: '::0/64',
},
{
ip: 'ef00::',
dbFile: 'MaxMind-DB-no-ipv4-search-tree.mmdb',
expectedPrefixLength: 1,
expectedRecord: null,
},
];

for (const test of tests) {
it(`should test ${test.ip} in ${test.dbFile}`, async () => {
const geoIp = await maxmind.open(path.join(dataDir, test.dbFile));

assert.deepStrictEqual(geoIp.getWithPrefixLength(test.ip), [
test.expectedRecord,
test.expectedPrefixLength,
]);
});
}
});
});
106 changes: 66 additions & 40 deletions src/reader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,94 @@ import Reader from './reader';
describe('reader', () => {
const dataDir = path.join(__dirname, '../test/data/test-data');
const read = (dir: string, filepath: string): Buffer =>
fs.readFileSync(path.join(dir, filepath));
fs.readFileSync(path.join(dir, filepath))

describe('findAddressInTree()', () => {
it('should work for most basic case', () => {
const reader: any = new Reader(read(dataDir, 'GeoIP2-City-Test.mmdb'));
assert.strictEqual(reader.findAddressInTree('1.1.1.1'), null);
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.1'), [null, 8]);
});

type treeRecord = [number | null, number];

it('should return correct value: city database', () => {
const reader: any = new Reader(read(dataDir, 'GeoIP2-City-Test.mmdb'));
assert.strictEqual(reader.findAddressInTree('1.1.1.1'), null);
assert.strictEqual(reader.findAddressInTree('175.16.199.1'), 3383);
assert.strictEqual(reader.findAddressInTree('175.16.199.88'), 3383);
assert.strictEqual(reader.findAddressInTree('175.16.199.255'), 3383);
assert.strictEqual(reader.findAddressInTree('::175.16.199.255'), 3383);
assert.strictEqual(
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.1'), [null, 8]);
assert.deepStrictEqual(reader.findAddressInTree('175.16.199.1'), [
3383,
24,
]);
assert.deepStrictEqual(reader.findAddressInTree('175.16.199.88'), [
3383,
24,
]);
assert.deepStrictEqual(reader.findAddressInTree('175.16.199.255'), [
3383,
24,
]);
assert.deepStrictEqual(reader.findAddressInTree('::175.16.199.255'), [
3383,
120,
]);
assert.deepStrictEqual(
reader.findAddressInTree('::ffff:175.16.199.255'),
3383
[3383, 120]
);
assert.strictEqual(reader.findAddressInTree('2a02:cf40:ffff::'), 5114);
assert.strictEqual(reader.findAddressInTree('2a02:cf47:0000::'), 5114);
assert.strictEqual(
assert.deepStrictEqual(reader.findAddressInTree('2a02:cf40:ffff::'), [
5114,
29,
]);
assert.deepStrictEqual(reader.findAddressInTree('2a02:cf47:0000::'), [
5114,
29,
]);
assert.deepStrictEqual(
reader.findAddressInTree('2a02:cf47:0000:fff0:ffff::'),
5114
[5114, 29]
);
assert.strictEqual(reader.findAddressInTree('2a02:cf48:0000::'), null);
assert.deepStrictEqual(reader.findAddressInTree('2a02:cf48:0000::'), [
null,
29,
]);
});

it('should return correct value: string entries', () => {
const reader: any = new Reader(
read(dataDir, 'MaxMind-DB-string-value-entries.mmdb')
);
assert.strictEqual(reader.findAddressInTree('1.1.1.1'), 225);
assert.strictEqual(reader.findAddressInTree('1.1.1.2'), 214);
assert.strictEqual(reader.findAddressInTree('175.2.1.1'), null);
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.1'), [225, 32]);
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.2'), [214, 31]);
assert.deepStrictEqual(reader.findAddressInTree('175.2.1.1'), [null, 7]);
});

describe('various record sizes and ip versions', () => {
const ips = {
const ips: Record<string, Record<string, treeRecord>> = {
v4: {
'1.1.1.1': 229,
'1.1.1.2': 217,
'1.1.1.32': 241,
'1.1.1.33': null,
'1.1.1.1': [229, 32],
'1.1.1.2': [217, 31],
'1.1.1.32': [241, 32],
'1.1.1.33': [null, 32],
},
v6: {
'::1:ffff:fffa': null,
'::1:ffff:ffff': 432,
'::2:0000:0000': 450,
'::2:0000:0060': null,
'::1:ffff:fffa': [null, 126],
'::1:ffff:ffff': [432, 128],
'::2:0000:0000': [450, 122],
'::2:0000:0060': [null, 123],
},
mix: {
'1.1.1.1': 518,
'1.1.1.2': 504,
'1.1.1.32': 532,
'1.1.1.33': null,
'::1:ffff:fffa': null,
'::1:ffff:ffff': 547,
'::2:0000:0000': 565,
'::2:0000:0060': null,
'1.1.1.1': [518, 32],
'1.1.1.2': [504, 31],
'1.1.1.32': [532, 32],
'1.1.1.33': [null, 32],
'::1:ffff:fffa': [null, 126],
'::1:ffff:ffff': [547, 128],
'::2:0000:0000': [565, 122],
'::2:0000:0060': [null, 123],
},
};

interface Scenarios {
[key: string]: Record<string, number | null>;
[key: string]: Record<string, treeRecord>;
}

const scenarios: Scenarios = {
Expand All @@ -90,7 +113,7 @@ describe('reader', () => {
const reader: any = new Reader(read(dataDir, '' + item));
const list = scenarios[item];
for (const ip in list) {
assert.strictEqual(
assert.deepStrictEqual(
reader.findAddressInTree(ip),
list[ip],
'IP: ' + ip
Expand All @@ -105,17 +128,20 @@ describe('reader', () => {
const reader: any = new Reader(
read(dataDir, 'MaxMind-DB-no-ipv4-search-tree.mmdb')
);
assert.strictEqual(reader.findAddressInTree('::1:ffff:ffff'), 80);
assert.strictEqual(reader.findAddressInTree('1.1.1.1'), 80);
assert.deepStrictEqual(reader.findAddressInTree('::1:ffff:ffff'), [
80,
64,
]);
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.1'), [80, 0]);
});

it('should behave fine when search tree is broken', () => {
// TODO: find out in what way the file is broken
const reader: any = new Reader(
read(dataDir, 'MaxMind-DB-test-broken-search-tree-24.mmdb')
);
assert.strictEqual(reader.findAddressInTree('1.1.1.1'), 229);
assert.strictEqual(reader.findAddressInTree('1.1.1.2'), 217);
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.1'), [229, 32]);
assert.deepStrictEqual(reader.findAddressInTree('1.1.1.2'), [217, 31]);
});
});

Expand Down
Loading

0 comments on commit 3623da3

Please sign in to comment.