ahn-restful-rpc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ # Use path_nesting to specify an arbitrarily nested. Could be used for additional security or in HTTP reverse proxy server.
2
+ path_nesting: /
3
+
4
+ port: 5000
5
+
6
+ # The "handler" option here can be any valid Rack::Handler constant name.
7
+ # Other options: WEBrick, EventedMongrel.
8
+ # If you don't know the differences between these, "Mongrel" is definitely a good choice.
9
+ handler: WEBrick
10
+
11
+ # In a production system, you should make this "false" since
12
+ show_exceptions: true
13
+
14
+ # The "authentication" config option can either be "false" or key/value pairs representing allowed usernames and passwords.
15
+
16
+ #authentication: false
17
+ authentication:
18
+ jicksta: roflcopterz
19
+ foo: bar6213671682
20
+
21
+ access: everyone # When allowing "everyone" access, no IPs are blocked.
22
+ #access: whitelist # When using a whitelist, the "whitelist" data below will be used.
23
+ #access: blacklist # When using a blacklist, the "blacklist" data below will be used.
24
+
25
+ # This is a list of IPs which are exclusively allowed to call this web service.
26
+ # Note: whitelists are far more secure than blacklists.
27
+ whitelist:
28
+ - 127.0.0.1
29
+ - 192.168.*.*
30
+
31
+ # This is a list of the IPs which are explicitly NOT allowed to call this web service. This will only be used if "access" is
32
+ # set to "blacklist" above.
33
+ blacklist:
34
+ - 100.200.100.200
@@ -0,0 +1,105 @@
1
+ begin
2
+ require 'rack'
3
+ require 'json'
4
+ rescue LoadError
5
+ abort "ERROR: restful_rpc requires the 'rack' and 'json' gems"
6
+ end
7
+
8
+ # Don't you love regular expressions? Matches only 0-255 octets. Recognizes "*" as an octet wildcard.
9
+ VALID_IP_ADDRESS = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|\*)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|\*)$/
10
+
11
+ def ip_allowed?(ip)
12
+ raise ArgumentError, "#{ip.inspect} is not a valid IP address!" unless ip.kind_of?(String) && ip =~ VALID_IP_ADDRESS
13
+
14
+ octets = ip.split "."
15
+
16
+ case COMPONENTS.restful_rpc["access"]
17
+ when "everyone"
18
+ true
19
+ when "whitelist"
20
+ whitelist = COMPONENTS.restful_rpc["whitelist"]
21
+ !! whitelist.find do |pattern|
22
+ pattern_octets = pattern.split "."
23
+ # Traverse both arrays in parallel
24
+ octets.zip(pattern_octets).map do |octet, octet_pattern|
25
+ octet_pattern == "*" ? true : (octet == octet_pattern)
26
+ end == [true, true, true, true]
27
+ end
28
+ when "blacklist"
29
+ blacklist = COMPONENTS.restful_rpc["blacklist"]
30
+ ! blacklist.find do |pattern|
31
+ pattern_octets = pattern.split "."
32
+ # Traverse both arrays in parallel
33
+ octets.zip(pattern_octets).map do |octet, octet_pattern|
34
+ octet_pattern == "*" ? true : (octet == octet_pattern)
35
+ end == [true, true, true, true]
36
+ end
37
+ else
38
+ raise Adhearsion::Components::ConfigurationError, 'Unrecognized "access" configuration value!'
39
+ end
40
+ end
41
+
42
+ RESTFUL_API_HANDLER = lambda do |env|
43
+ json = env["rack.input"].read
44
+
45
+ # Return "Bad Request" HTTP error if the client forgot
46
+ return [400, {}, "You must POST a valid JSON object!"] if json.blank?
47
+
48
+ json = JSON.parse json
49
+
50
+ nesting = COMPONENTS.restful_rpc["path_nesting"]
51
+ path = env["PATH_INFO"]
52
+
53
+ return [404, {}, "This resource does not respond to #{path.inspect}"] unless path[0...nesting.size] == nesting
54
+
55
+ path = path[nesting.size..-1]
56
+
57
+ return [404, {"Content-Type" => "application/json"}, "You cannot nest method names!"] if path.include?("/")
58
+
59
+ rpc_object = Adhearsion::Components.component_manager.extend_object_with(Object.new, :rpc)
60
+
61
+ # TODO: set the content-type and other HTTP headers
62
+ response_object = rpc_object.send(path, *json)
63
+ [200, {"Content-Type" => "application/json"}, Array(response_object.to_json)]
64
+
65
+ end
66
+
67
+ initialization do
68
+ config = COMPONENTS.send :'ahn-restful-rpc'
69
+
70
+ api = RESTFUL_API_HANDLER
71
+
72
+ port = config["port"] || 5000
73
+ authentication = config["authentication"]
74
+ show_exceptions = config["show_exceptions"]
75
+ handler = Rack::Handler.const_get(config["handler"] || "Mongrel")
76
+
77
+ if authentication
78
+ api = Rack::Auth::Basic.new(api) do |username, password|
79
+ authentication[username] == password
80
+ end
81
+ api.realm = "Adhearsion API"
82
+ end
83
+
84
+ if show_exceptions
85
+ api = Rack::ShowStatus.new(Rack::ShowExceptions.new(api))
86
+ end
87
+
88
+ Thread.new do
89
+ handler.run api, :Port => port
90
+ end
91
+ end
92
+
93
+ methods_for :rpc do
94
+ [:send_action, :introduce, :originate, :call_into_context, :call_and_exec, :ping].each do |method_name|
95
+ define_method("restful_#{method_name}") do |*args|
96
+ if VoIP::Asterisk.manager_interface
97
+ response = VoIP::Asterisk.manager_interface.send(method_name, *args)
98
+ {:result => true}
99
+ else
100
+ ahn_log.ami_remote.error "AMI has not been enabled in startup.rb!"
101
+ {:result => false}
102
+ end
103
+ end
104
+ end
105
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ahn-restful-rpc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jay Phillips
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-26 00:00:00.000000000 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: adhearsion
17
+ requirement: &2156809400 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2156809400
26
+ - !ruby/object:Gem::Dependency
27
+ name: json
28
+ requirement: &2156808940 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *2156808940
37
+ - !ruby/object:Gem::Dependency
38
+ name: rack
39
+ requirement: &2156808520 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *2156808520
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: &2156808100 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *2156808100
59
+ description: Allows remote procedure calls over an HTTP API integrated in Adhearsion
60
+ email: dev&adhearsion.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - lib/ahn-restful-rpc.rb
66
+ - config/ahn-restful-rpc.yml
67
+ has_rdoc: false
68
+ homepage: https://github.com/adhearsion/ahn-restful-rpc
69
+ licenses: []
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.6.2
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: Provides a RESTful RPC API on Adhearsion
92
+ test_files: []