Files: 012e32d5ba7c8cc7ea4d15234b2715ffc1f0e154 / convenient.js
3328 bytesRaw
1 | // Copyright 2012 Iris Couch, all rights reserved. |
2 | // |
3 | // Convenience routines to make it easier to build a service |
4 | |
5 | require('defaultable')(module, |
6 | { 'convenient' : true |
7 | , 'ttl' : 10 |
8 | }, function(module, exports, DEFS, require) { |
9 | |
10 | function noop() {} |
11 | |
12 | module.exports = { 'init_response' : init_response |
13 | , 'final_response': final_response |
14 | , 'seconds': seconds |
15 | , 'serial': serial |
16 | } |
17 | |
18 | if(! DEFS.convenient) { |
19 | module.exports.init_response = noop |
20 | module.exports.final_response = noop |
21 | } |
22 | |
23 | |
24 | function init_response(res) { |
25 | res.type = 'response' |
26 | } |
27 | |
28 | function final_response(res, value) { |
29 | if(Array.isArray(value)) { |
30 | res.answer = (res.answer || []).concat(value) |
31 | value = undefined |
32 | } else if(typeof value == 'object') { |
33 | res = new res.constructor(value, value.connection || res.connection) |
34 | value = undefined |
35 | } |
36 | |
37 | var questions = res.question || [] |
38 | , answers = res.answer || [] |
39 | , authorities = res.authority || [] |
40 | , additionals = res.additional || [] |
41 | |
42 | res.recursion_available = false |
43 | |
44 | // Find the zone of authority for this record, if any. |
45 | var question = questions[0] |
46 | , names = question && question.name && question.name.split(/\./) |
47 | , zone, soa_record |
48 | |
49 | while(names && names.length) { |
50 | zone = names.join('.') |
51 | names.shift() |
52 | |
53 | soa_record = res.connection.server.zones[zone] |
54 | if(soa_record) |
55 | break |
56 | } |
57 | |
58 | if(soa_record) |
59 | res.authoritative = true |
60 | |
61 | // Add convenience for typical name resolution. |
62 | if(questions.length == 1 && question.kind() == 'IN A') { |
63 | // If the value given is an IP address, make that the answer. |
64 | if(typeof value == 'string' && answers.length == 0) |
65 | res.answer.push({'class':'IN', 'type':'A', 'name':question.name, 'data':value}) |
66 | } |
67 | |
68 | // Convenience for SOA queries |
69 | else if(questions.length == 1 && question.kind() == 'IN SOA') { |
70 | // Respond with the SOA record for this zone if necessary and possible. |
71 | if(answers.length == 0 && soa_record && soa_record.name == question.name) |
72 | res.answer.push(soa_record) |
73 | } |
74 | |
75 | // If the server is authoritative for a zone, add an SOA record if there is no good answer. |
76 | if(soa_record && questions.length == 1 && answers.length == 0 && authorities.length == 0) |
77 | res.authority.push(soa_record) |
78 | |
79 | // Set missing TTLs |
80 | answers.forEach(well_formed_record) |
81 | authorities.forEach(well_formed_record) |
82 | additionals.forEach(well_formed_record) |
83 | |
84 | return res |
85 | |
86 | function well_formed_record(record) { |
87 | record.class = record.class || 'IN' |
88 | } |
89 | } |
90 | |
91 | |
92 | function serial(value) { |
93 | if(value != 'now') |
94 | return value |
95 | |
96 | // Otherwise, "now" is the current Unix time (no milliseconds). |
97 | var now = new Date |
98 | return Math.floor(now.getTime() / 1000) |
99 | } |
100 | |
101 | // Convert various string values to seconds. |
102 | function seconds(value) { |
103 | if(typeof value != 'string') |
104 | return value |
105 | |
106 | var match |
107 | if(match = value.match(/^(\d+)s$/)) // seconds |
108 | return +match[1] |
109 | |
110 | if(match = value.match(/^(\d+)m$/)) // minutes |
111 | return +match[1] * 60 |
112 | |
113 | if(match = value.match(/^(\d+)h$/)) // hours |
114 | return +match[1] * 60 * 60 |
115 | |
116 | if(match = value.match(/^(\d+)d$/)) // days |
117 | return +match[1] * 60 * 60 * 24 |
118 | |
119 | if(match = value.match(/^(\d+)w$/)) // weeks |
120 | return +match[1] * 60 * 60 * 24 * 7 |
121 | } |
122 | |
123 | |
124 | }) // defaultable |
125 |
Built with git-ssb-web