作者的NPM學習之路
在NPM這麼方便的世界裡,筆者在遇到新的IDEA時,會在NPM中搜尋相關可用套件,也會透過這些套件的source code與dependency找尋相關資訊的蛛絲馬跡...
曾經的需求
筆者曾經授命開發一個動態DNS服務,需要透過API動態生成可以在網際網路上可以查詢的DNS紀錄... 當時在遍尋DNS相關工具之後,突然覺得,如果可以使用DNS協定套件來開發DNS Server,應該會是最佳解法... 而Node.js正式具備這樣能力的一個程式語言之一...
放大範圍查詢NPM
複習一下NPM的搜尋方式...
npm search [關鍵字]
在這個需求中,可以透過npm search dns來找找有誰發布DNS相關的套件...
$ npm search dns
NAME DESCRIPTION AUTHOR
address Get current machine IP, MAC and DNS servers. =fengmk2
addressbook Addressbook keeps tracking available node instances backed… =kazuyukit
...(skip)
ddns-client
ddns-daemon A Simple Dynamic Daemon using Node.js and Route53 =jpillora
devdns Simple DNS server for Developers =justcompi
dgate Domain gateway, a simple clustered HTTP virtual host router =carlos8f
dgs The DNS Golden Standard: A DNS server aiming to return all… =willscott
diont Easy Service Discovery on Local Networks in pure Javascript =willemmul
dlouc-flare To run at a server which has a dynamic IP and cloudflare… =xadillax
dme2 This module allows one to connect to DNSMadeEasy's APIs… =evanlucas
dnc A CLI tool to check domain names configuration and… =fcambus
dns A DNS Server with a REST API =hbouvier
dns-checker
dns-debug Monkey-patch for dns to enable some logging when… =diunko
dns-graceful-stack-switch Graceful stack switching in dns.lookup. This will fix… =floatdro
...(skip)
搜尋的結果會包含關鍵字與描述中包含dns的所有應用,因此關鍵字的完整程度可以降低搜尋結果的大小...
在這些結果當中,通常我們會以套件中有包含我們關鍵字的為優先查看的對象... 我們可以先看看dns這個套件,在他的描述中:
dns A CLI tool to check domain names configuration and… =fcambus
原則上,跟我們需要的套件有所相關...,我們可以透過npm show來查看這個套件的相關資訊...
$ npm show dns
{ name: 'dns',
description: 'A DNS Server with a REST API',
'dist-tags': { latest: '0.2.2' },
versions:
[ '0.0.7',
'0.0.8',
'0.0.9',
'0.1.0',
'0.1.1',
'0.1.2',
'0.1.3',
'0.1.4',
'0.1.5',
'0.2.0',
'0.2.1',
'0.2.2' ],
maintainers: 'hbouvier <[email protected]>',
time:
{ modified: '2014-09-17T10:44:40.596Z',
created: '2014-06-28T22:16:03.986Z',
'0.0.1': '2014-06-28T22:16:03.986Z',
'0.0.2': '2014-06-28T22:50:29.510Z',
'0.0.3': '2014-06-29T03:24:31.800Z',
'0.0.4': '2014-06-29T13:33:08.114Z',
'0.0.7': '2014-06-29T15:22:51.759Z',
'0.0.8': '2014-07-01T21:41:01.538Z',
'0.0.9': '2014-07-05T20:26:44.790Z',
'0.1.0': '2014-07-06T15:40:59.549Z',
'0.1.1': '2014-07-06T22:21:34.135Z',
'0.1.2': '2014-07-07T00:08:57.778Z',
'0.1.3': '2014-07-23T01:44:02.123Z',
'0.1.4': '2014-07-23T15:48:47.142Z',
'0.1.5': '2014-09-16T00:17:20.768Z',
'0.2.0': '2014-09-16T03:10:16.523Z',
'0.2.1': '2014-09-17T02:01:33.526Z',
'0.2.2': '2014-09-17T10:44:40.596Z' },
homepage: 'https://github.com/hbouvier/dns',
keywords: [ 'dns', 'REST' ],
repository:
{ type: 'git',
url: 'https://github.com/hbouvier/dns.git' },
author: 'Henri Bouvier',
bugs: { url: 'https://github.com/hbouvier/dns/issues' },
readmeFilename: 'README.md',
users: { aksalj: true },
version: '0.2.2',
dependencies:
{ winston: '0.7.3',
'hbo-dnsd': '0.9.8',
'native-dns': '0.6.1',
'node-options': '0.0.6',
tomahawk: '0.1.6',
'tomahawk-plugin-kv-memory-store': '0.0.3' },
engines: { node: '>= 0.10.0 < 0.11.0' },
main: './lib/dns.js',
bin: { dns: './bin/dns' },
scripts: { start: 'bin/dns' },
configuration:
{ name: 'DNS',
context: '/',
level: 'info',
port: 8053,
plugins:
{ store:
{ context: '/dns/api/v1',
interval: 1000,
implementation: 'tomahawk-plugin-kv-memory-store',
filename: '${HOME}/.dns/dns-store' } },
dns:
{ host: '0.0.0.0',
port: 53,
zone: 'local.dev',
ttl: 3600,
prefix: 'dns:',
primary: '8.8.8.8',
secondary: '8.8.4.4',
timeout: 1000 } },
dist:
{ shasum: 'a8477ca26b835842c3125204d8cbcdd6af98c9ec',
tarball: 'http://registry.npmjs.org/dns/-/dns-0.2.2.tgz' },
directories: {} }
透過dns套件的詳細資訊,我們可以看到他的中間有提供作者針對這個套件所release的web site資訊
homepage: 'https://github.com/hbouvier/dns'
查詢這個github repository後,可以找到相關的資訊... 其中,Github的README中告訴我們,這是個DNS server,擁有自己的Web Console: http://localhost:8053,有一定的完成度... 在這邊我們可以試著安裝起來,確認一下是否可用,可以提供作為我們改寫的基礎...
另外,在dependency中,我們可以看到...
dependencies:
{ winston: '0.7.3',
'hbo-dnsd': '0.9.8',
'native-dns': '0.6.1',
'node-options': '0.0.6',
tomahawk: '0.1.6',
'tomahawk-plugin-kv-memory-store': '0.0.3' }
這是作者在dns這個套件中使用到的相關模組,待我們一個一個查看... 其中native-dns即是整個DNS協定的核心...
$ npm show native-dns
{ name: 'native-dns',
description: 'Replacement for the core DNS module, includes server implementation',
'dist-tags': { latest: '0.7.0' },
versions:
[ '0.0.1',
'0.0.2',
...
'0.4.1',
'0.6.1',
'0.7.0' ],
maintainers:
[ 'tjfontaine <[email protected]>',
'taoeffect <[email protected]>' ],
time:
{ modified: '2014-10-06T00:18:32.427Z',
created: '2012-01-25T00:55:45.435Z',
'0.0.1': '2012-01-25T00:55:46.894Z',
'0.0.2': '2012-02-14T17:40:49.748Z',
...
'0.4.0': '2013-01-10T01:16:17.334Z',
'0.4.1': '2013-02-15T07:42:54.609Z',
'0.6.1': '2014-04-15T14:52:14.529Z',
'0.7.0': '2014-10-06T00:18:32.427Z' },
repository:
{ type: 'git',
url: 'http://github.com/tjfontaine/node-dns.git' },
users:
{ fgribreau: true,
awaterma: true,
silverwind: true,
roshanravi10: true },
homepage: 'http://github.com/tjfontaine/node-dns',
keywords: [ 'dns', 'bind', 'native' ],
contributors: 'Timothy J Fontaine <[email protected]>',
bugs: { url: 'http://github.com/tjfontaine/node-dns/issues' },
readmeFilename: 'README.md',
version: '0.7.0',
authors:
[ 'Timothy J Fontaine <[email protected]> (http://atxconsulting.com)',
'Greg Slepak <[email protected]> (https://twitter.com/taoeffect)',
'Matthieu Rakotojaona' ],
main: 'dns.js',
engines: { node: '>= 0.5.0' },
scripts: { test: 'nodeunit test' },
dependencies:
{ 'ipaddr.js': '~0.1.3',
'native-dns-cache': '~0.0.2',
'native-dns-packet': '~0.1.1' },
devDependencies: { optimist: '', nodeunit: '>= 0.7.4' },
gitHead: '6ce835d9625a45ea7c8e8e71e36e1ebee767969e',
dist:
{ shasum: 'df418636f08fb29e8fcb7ef142c822a1588ba5b7',
tarball: 'http://registry.npmjs.org/native-dns/-/native-dns-0.7.0.tgz' },
directories: {} }
在native-dns的查詢中,我們可以找到該套件的Github repository:http://github.com/tjfontaine/node-dns.git,其中,執行使用者的Server端範例,可以看到:
var dns = require('dns'),
server = dns.createServer();
server.on('request', function (request, response) {
//console.log(request)
response.answer.push(dns.A({
name: request.question[0].name,
address: '127.0.0.1',
ttl: 600,
}));
response.answer.push(dns.A({
name: request.question[0].name,
address: '127.0.0.2',
ttl: 600,
}));
response.additional.push(dns.A({
name: 'hostA.example.org',
address: '127.0.0.3',
ttl: 600,
}));
response.send();
});
server.on('error', function (err, buff, req, res) {
console.log(err.stack);
});
server.serve(15353);
一個簡單的DNS伺服器就可以執行起來... 在Trace source code之後,我們可以看到底層作者實作DNS協定的Code...
而我們的需求,即是希望操控DNS回應的部分,因此只要改寫Code裡面hard code的回應部分,讓資料來自於某個persistance的位置,例如資料庫,即可以讓其他系統透過中繼介面(例如:資料庫),來達到DNS record可編輯的效果...這邊先保留這部份實作,待後面篇幅再行介紹。