Skip to content
Newer
Older
100644 84 lines (75 sloc) 2.48 KB
bcafd3d @jpf Licensing code under the Apache License, Version 2.0
authored Dec 26, 2009
1 #
2 # jsondns.rb
3 # Sinatra web application that provides a REST based DNS interface.
4 #
5 # Copyright 2009 Joel Franusic
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18
74d730e @jpf Move libraries to /lib. Add JSONP support
authored Dec 26, 2009
19 $LOAD_PATH.push(File.dirname(__FILE__) + '/lib')
b0d1788 @jpf rename library, etc
authored Dec 26, 2009
20 require 'dnsruby-jsonquery'
f0ee423 @jpf Adding jsondns
authored Dec 25, 2009
21 require 'sinatra'
22
9ddd24e @jpf Add Cache-Control headers to output with TTL of the reply as the value
authored Dec 27, 2009
23 def ttl_for(answer)
24 ttl = 5 # set a 5 second ttl
f8a5cfe @brianmario symbolize keys
brianmario authored Dec 31, 2009
25 answer_hash = Yajl::Parser.new(:symbolize_keys => true).parse(answer)
26 if answer_hash[:header][:rcode] == 'NOERROR' && answer_hash[:answer][0]
27 ttl = answer_hash[:answer][0][:ttl]
9ddd24e @jpf Add Cache-Control headers to output with TTL of the reply as the value
authored Dec 27, 2009
28 end
29 ttl
30 end
31
63f80f2 @jpf not Google DNS anymore
authored Jan 4, 2010
32 resolver = Dnsruby::Resolver.new({:nameserver => "4.2.2.2"})
f0ee423 @jpf Adding jsondns
authored Dec 26, 2009
33
7d7e7d1 @jpf Return HTTP status codes to reflect the DNS RCODE
authored Dec 27, 2009
34 def status_for(answer)
35 status = 503
f8a5cfe @brianmario symbolize keys
brianmario authored Dec 30, 2009
36 answer_hash = Yajl::Parser.new(:symbolize_keys => true).parse(answer)
37 rcode = answer_hash[:header][:rcode]
38 aa = answer_hash[:header][:aa]
7d7e7d1 @jpf Return HTTP status codes to reflect the DNS RCODE
authored Dec 27, 2009
39
40 # These cover RFC 1035, I haven't looked at RFC 2136 yet ...
41 if rcode == 'NOERROR' && aa == true
42 status = 200 # OK
43 elsif rcode == 'NOERROR' && aa == false
44 status = 203 # Non-Authoritative Information
45 elsif rcode == 'FORMERR'
46 status = 400 # Bad Request
47 elsif rcode == 'SERVFAIL'
48 status = 503 # Service Unavailable
49 elsif rcode == 'NXDOMAIN'
50 status = 404 # Not Found
51 elsif rcode == 'NOTIMP'
52 status = 501 # Not Implemented
53 elsif rcode == 'REFUSED'
54 status = 403 # Forbidden
55 end
56 status
57 end
58
f7acb36 @jpf Add a default view, handle incomplete domain names
authored Dec 26, 2009
59 get '/' do
60 erb :index
61 end
b0d1788 @jpf rename library, etc
authored Dec 27, 2009
62
f0ee423 @jpf Adding jsondns
authored Dec 26, 2009
63 get '/IN/:domain/:type' do
74d730e @jpf Move libraries to /lib. Add JSONP support
authored Dec 27, 2009
64 answer = resolver.jsonquery(params[:domain],params[:type])
7d7e7d1 @jpf Return HTTP status codes to reflect the DNS RCODE
authored Dec 27, 2009
65 status status_for(answer)
2a6c4b9 @jpf Content-Type: text/plain
authored Dec 30, 2009
66 response.headers['Content-Type'] = 'text/plain'
9ddd24e @jpf Add Cache-Control headers to output with TTL of the reply as the value
authored Dec 27, 2009
67 response.headers['Cache-Control'] = 'public, max-age=' + ttl_for(answer).to_s
af9b43e @jpf callback input validation thanks to tlrobinson
authored Dec 26, 2009
68 if params[:callback] =~ /^[a-zA-Z_$][a-zA-Z0-9_$]*$/
e9b671c @jpf return HTTP status 200 if a callback is defined
authored Aug 24, 2010
69 status 200
74d730e @jpf Move libraries to /lib. Add JSONP support
authored Dec 27, 2009
70 params[:callback] + '(' + answer + ')' # JSONP
71 else
72 answer
73 end
f0ee423 @jpf Adding jsondns
authored Dec 26, 2009
74 end
75
9cb1d11 @jpf Adding a comment.
authored Jan 27, 2012
76 # Return a blank result for invalid requests.
f7acb36 @jpf Add a default view, handle incomplete domain names
authored Dec 27, 2009
77 get '/IN*' do
7d7e7d1 @jpf Return HTTP status codes to reflect the DNS RCODE
authored Dec 27, 2009
78 answer = resolver.jsonquery(nil,nil)
79 status status_for(answer)
b7cb38e @mibe Use "text/plain" as media type even for erroneous requests.
mibe authored Feb 6, 2011
80 response.headers['Content-Type'] = 'text/plain'
7d7e7d1 @jpf Return HTTP status codes to reflect the DNS RCODE
authored Dec 27, 2009
81 response.headers['Cache-Control'] = 'public, max-age=' + ttl_for(answer).to_s
82 answer
f7acb36 @jpf Add a default view, handle incomplete domain names
authored Dec 27, 2009
83 end
Something went wrong with that request. Please try again.