jsonrpc2 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/bin/jsonrpc2 ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems" # ruby1.9 doesn't "require" it though
3
+ require "thor"
4
+ require 'jsonrpc2/client'
5
+ require 'json'
6
+ require 'pp'
7
+
8
+ class JSONClient < Thor
9
+ method_option :user, :type => :string
10
+ method_option :pass, :type => :string
11
+ desc "call URI METHOD [PARAMS]", "Call "
12
+ def call uri, method, params=nil
13
+ STDOUT << "#{uri}##{method}(#{params})"
14
+ uri = "http://#{uri}" unless uri =~ %r'://'
15
+
16
+ client = JSONRPC2::Client.new(uri, options)
17
+ STDOUT << " => "
18
+ begin
19
+ pp client.call(method, JSON.parse(params))
20
+ rescue JSONRPC2::RemoteAuthError => e
21
+ puts "ERR\nFAIL: #{e.message}"
22
+ rescue JSONRPC2::RemoteError => e
23
+ puts "ERR\nFAIL: #{e.message}"
24
+ end
25
+ end
26
+ end
27
+
28
+ JSONClient.start
data/example/config.ru CHANGED
@@ -4,15 +4,15 @@ require 'jsonrpc2/interface'
4
4
  class ::Object::Calculator < JSONRPC2::Interface
5
5
  title "JSON-RPC2 Calculator"
6
6
  introduction "This interface allows basic maths calculations via JSON-RPC2"
7
- auth_with JSONRPC2::BasicAuth.new({'user' => 'secretword'})
7
+ auth_with JSONRPC2::BasicAuth.new({'user' => 'secretword', 'admin' => 'password'})
8
8
 
9
9
  section 'Simple Ops' do
10
10
  desc 'Multiply two numbers'
11
11
  param 'a', 'Number', 'a'
12
12
  param 'b', 'Number', 'b'
13
13
  result 'Number', 'a * b'
14
- def mul args
15
- args['a'] * args['b']
14
+ def mul
15
+ params['a'] * params['b']
16
16
  end
17
17
 
18
18
  desc 'Add numbers'
@@ -22,9 +22,12 @@ class ::Object::Calculator < JSONRPC2::Interface
22
22
  param 'b', 'Number', 'Second number'
23
23
  optional 'c', 'Number', 'Third number'
24
24
  result 'Number', 'a + b + c'
25
- def sum args
26
- val = args['a'] + args['b']
27
- val += args['c'] if args['c']
25
+ def sum
26
+ val = params['a'] + params['b']
27
+ val += params['c'] if params['c']
28
+
29
+ return 42 if auth == 'admin'
30
+
28
31
  val
29
32
  end
30
33
  end
data/jsonrpc2.gemspec CHANGED
@@ -54,4 +54,5 @@ EOD
54
54
  gem.add_dependency("httpclient")
55
55
  gem.add_dependency("json")
56
56
  gem.add_dependency("RedCloth")
57
+ gem.add_dependency('thor')
57
58
  end
data/lib/jsonrpc2/auth.rb CHANGED
@@ -89,14 +89,15 @@ class BasicAuth < HttpAuth
89
89
 
90
90
  # Checks users hash and then the block given to the constructor to
91
91
  # verify username / password.
92
+ # @return [String,false] Username or nothing
92
93
  def user_valid?(user, pass)
93
94
  if @users && @users.respond_to?(:[])
94
95
  if expected = @users[user]
95
- return pass == expected
96
+ return user if pass == expected
96
97
  end
97
98
  end
98
99
  if @lookup
99
- return @lookup.call(user, pass)
100
+ return user if @lookup.call(user, pass)
100
101
  end
101
102
  false
102
103
  end
@@ -6,6 +6,10 @@ module JSONRPC2
6
6
  class RemoteError < RuntimeError
7
7
  end
8
8
 
9
+ # JSON RPC remote auth error
10
+ class RemoteAuthError < RemoteError
11
+ end
12
+
9
13
  # Simple JSONRPC client
10
14
  class Client
11
15
  # Create client object
@@ -36,8 +40,8 @@ class Client
36
40
  headers = headers.merge(options[:headers])
37
41
  end
38
42
 
39
- if options[:auth]
40
- @client.set_auth(@uri, options[:auth][:username], options[:auth][:password])
43
+ if options[:user] && options[:pass]
44
+ @client.set_auth(@uri, options[:user], options[:pass])
41
45
  end
42
46
  result = @client.post(@uri,
43
47
  { 'method' => method, 'params' => args, 'jsonrpc' => '2.0', 'id' => (@id+=1) }.to_json,
@@ -49,8 +53,17 @@ class Client
49
53
  if data.has_key?('result')
50
54
  return data['result']
51
55
  else
52
- raise RemoteError, data['error']['message']
56
+ if data['error']['code'] == -32000 && data['error']['message'] =~ /^AuthFail/
57
+ raise RemoteAuthError, data['error']['message']
58
+ else
59
+ raise RemoteError, data['error']['message']
60
+ end
53
61
  end
62
+ elsif result.status_code == 401
63
+ if result.headers['WWW-Authenticate'].to_s =~ /realm="([^"]*?)"/
64
+ suffix = " for #{$1}"
65
+ end
66
+ raise RemoteAuthError, "Authentication failed#{suffix}"
54
67
  else
55
68
  raise result.body
56
69
  end
@@ -96,23 +96,28 @@ class Interface
96
96
  end
97
97
  # JSON error helper
98
98
  def response_error(code, message, data)
99
- { 'jsonrpc' => '2.0', 'error' => { 'code' => code, 'message' => message, 'data' => data }, 'id' => @id }
99
+ { 'jsonrpc' => '2.0', 'error' => { 'code' => code, 'message' => message, 'data' => data }, 'id' => (@jsonrpc_call && @jsonrpc_call['id'] || nil) }
100
100
  end
101
+ # Params helper
102
+ def params
103
+ @jsonrpc_call['params']
104
+ end
105
+ # Auth info
106
+ def auth
107
+ @jsonrpc_auth
108
+ end
101
109
  # Check call validity and authentication & make a single method call
102
110
  #
103
111
  # @param [Hash] rpc JSON-RPC-2 call
104
112
  def dispatch_single(rpc)
105
113
  unless rpc.has_key?('id') && rpc.has_key?('method') && rpc['jsonrpc'].eql?('2.0')
106
- @id = nil
107
114
  return response_error(-32600, 'Invalid request', nil)
108
115
  end
109
- @id = rpc['id']
110
- @method = rpc['method']
111
- @rpc = rpc
112
-
116
+ @jsonrpc_call = rpc
117
+
113
118
  begin
114
- if self.class.auth_with
115
- self.class.auth_with.client_check(@env, rpc) or raise AuthFail, "Invalid credentials"
119
+ if self.class.auth_with && ! @jsonrpc_auth
120
+ (@jsonrpc_auth = self.class.auth_with.client_check(@env, rpc)) or raise AuthFail, "Invalid credentials"
116
121
  end
117
122
 
118
123
  call(rpc['method'], rpc['id'], rpc['params'])
@@ -7,19 +7,23 @@ module JSONRPC2
7
7
  def to_textile
8
8
  return nil if @about.nil? or @about.empty?
9
9
  str = ""
10
+
10
11
  if @title
11
12
  str << "h1. #{@title}\n"
12
13
  else
13
14
  str << "h1. #{name}\n"
14
15
  end
16
+
15
17
  if @introduction
16
18
  str << "\nh2. Introduction\n\n#{@introduction}\n"
17
19
  end
18
20
 
21
+ # Output type descriptions
22
+ #
19
23
  unless @types.nil? or @types.empty?
20
- str << "\nh2. Types\n"
24
+ str << "\n\nh2. Types\n"
21
25
  @types.sort_by { |k,v| k }.each do |k,type|
22
- str << "\nh5. #{k} type\n"
26
+ str << "\n\nh5. #{k} type\n"
23
27
 
24
28
  str << "\n|_. Field |_. Type |_. Required? |_. Description |"
25
29
  type.fields.each do |field|
@@ -29,27 +33,32 @@ module JSONRPC2
29
33
  end
30
34
  end
31
35
 
32
- @sections.each do |section|
33
- str << "\nh2. #{section[:name]}\n"
36
+
37
+ # Output method definitions
38
+ #
39
+ (@sections||[]).each do |section|
40
+ str << "\n\nh2. #{section[:name]}\n"
34
41
  if section[:summary]
35
42
  str << "\n#{section[:summary]}\n"
36
43
  end
37
44
 
38
45
  str += to_textile_group(section).to_s
39
46
  end
47
+
40
48
  miscfn = to_textile_group({:name => nil})
41
49
  if miscfn
42
- str << "\nh2. Misc functions\n"
50
+ str << "\n\nh2. Misc functions\n" if @sections && ! @sections.empty?
43
51
  str << miscfn
44
52
  end
53
+
45
54
  str
46
55
  end
47
56
  # Returns method description in textile
48
57
  def method_to_textile(info)
49
58
  str = ''
50
- str << "\nh3. #{info[:name]}\n"
59
+ str << "\n\nh3. #{info[:name]}\n"
51
60
  str << "\n#{info[:desc]}\n" if info[:desc]
52
- str << "\nh5. Params\n"
61
+ str << "\n\nh5. Params\n"
53
62
  if info[:params].nil?
54
63
  str << "\n* _None_\n"
55
64
  elsif info[:params].is_a?(Array)
@@ -60,17 +69,17 @@ module JSONRPC2
60
69
  end
61
70
 
62
71
  if res = info[:returns]
63
- str << "\nh5. Result\n"
72
+ str << "\n\nh5. Result\n"
64
73
  str << "\n* @#{res[:type]}@"
65
74
  str << " - #{res[:desc]}" if res[:desc]
66
75
  str << "\n"
67
76
  else
68
- str << "\nh5. Result\n"
77
+ str << "\n\nh5. Result\n"
69
78
  str << "\n* @null@"
70
79
  end
71
80
 
72
81
  if examples = info[:examples]
73
- str << "\nh5. Sample usage\n"
82
+ str << "\n\nh5. Sample usage\n"
74
83
 
75
84
  nice_json = lambda do |data|
76
85
  JSON.pretty_unparse(data).gsub(/\n\n+/,"\n").gsub(/[{]\s+[}]/m, '{ }').gsub(/\[\s+\]/m, '[ ]')
@@ -1,5 +1,5 @@
1
1
  # JSONRPC2 namespace module
2
2
  module JSONRPC2
3
3
  # Version
4
- VERSION = "0.0.4"
4
+ VERSION = "0.0.5"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonrpc2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Geoff Youngs
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-07-17 00:00:00 Z
18
+ date: 2012-07-19 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: httpclient
@@ -59,6 +59,20 @@ dependencies:
59
59
  version: "0"
60
60
  type: :runtime
61
61
  version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: thor
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :runtime
75
+ version_requirements: *id004
62
76
  description: |+
63
77
  == Description
64
78
 
@@ -98,8 +112,8 @@ description: |+
98
112
 
99
113
  email:
100
114
  - git@intersect-uk.co.uk
101
- executables: []
102
-
115
+ executables:
116
+ - jsonrpc2
103
117
  extensions: []
104
118
 
105
119
  extra_rdoc_files: []
@@ -109,6 +123,7 @@ files:
109
123
  - Gemfile
110
124
  - README.markdown
111
125
  - Rakefile
126
+ - bin/jsonrpc2
112
127
  - example/config.ru
113
128
  - jsonrpc2.gemspec
114
129
  - lib/jsonrpc2.rb