Class: Jimson::HttpServer

Inherits:
EM::Connection
  • Object
show all
Includes:
EM::HttpServer
Defined in:
lib/jimson/server.rb

Constant Summary collapse

JSON_RPC_VERSION =
'2.0'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.handler=(handler) ⇒ Object



13
14
15
# File 'lib/jimson/server.rb', line 13

def self.handler=(handler)
  @@handler = handler
end

Instance Method Details

#create_response(request) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/jimson/server.rb', line 87

def create_response(request)
  params = request['params']
  begin
    if params.is_a?(Hash)
      result = @@handler.send(request['method'], params)
    else
      result = @@handler.send(request['method'], *params)
    end
  rescue NoMethodError
    raise Jimson::ServerError::MethodNotFound.new 
  rescue ArgumentError
    raise Jimson::ServerError::InvalidParams.new
  rescue
    raise Jimson::ServerError::ApplicationError.new($!)
  end

  response = success_response(request, result)

  # A Notification is a Request object without an "id" member.
  # The Server MUST NOT reply to a Notification, including those 
  # that are within a batch request.
  response = nil if !request.has_key?('id')

  response 
end

#error_response(error, request = nil) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/jimson/server.rb', line 113

def error_response(error, request = nil)
  resp = {
           'jsonrpc' => JSON_RPC_VERSION,
           'error'   => error.to_h,
         }
  if !!request && request.has_key?('id')
    resp['id'] = request['id'] 
  else
    resp['id'] = nil
  end

  resp
end

#handle_request(request) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/jimson/server.rb', line 48

def handle_request(request)
  response = nil
  begin
    if !validate_request(request)
      response = error_response(Jimson::ServerError::InvalidRequest.new)
    else
      response = create_response(request)
    end
  rescue Jimson::ServerError::Generic => e
    response = error_response(e, request)
  end

  response
end

#parse_request(post) ⇒ Object



135
136
137
138
139
# File 'lib/jimson/server.rb', line 135

def parse_request(post)
  data = JSON.parse(post)
  rescue 
    raise Jimson::ServerError::ParseError.new 
end

#process_http_requestObject



17
18
19
20
21
22
# File 'lib/jimson/server.rb', line 17

def process_http_request
  resp = EM::DelegatedHttpResponse.new( self )
  resp.status = 200
  resp.content = process_post(@http_post_content)
  resp.send_response
end

#process_post(content) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/jimson/server.rb', line 24

def process_post(content)
  begin
    request = parse_request(@http_post_content)
    if request.is_a?(Array)
      raise Jimson::ServerError::InvalidRequest.new if request.empty?
      response = request.map { |req| handle_request(req) }
    else
      response = handle_request(request)
    end
  rescue Jimson::ServerError::ParseError, Jimson::ServerError::InvalidRequest => e
    response = error_response(e)
  rescue Jimson::ServerError::Generic => e
    response = error_response(e, request)
  rescue StandardError, Exception
    response = error_response(Jimson::ServerError::InternalError.new)
  end

  response.compact! if response.is_a?(Array)

  return nil if response.nil? || (response.respond_to?(:empty?) && response.empty?)

  response.to_json
end

#success_response(request, result) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/jimson/server.rb', line 127

def success_response(request, result)
  {
    'jsonrpc' => JSON_RPC_VERSION,
    'result'  => result,  
    'id'      => request['id']
  }
end

#validate_request(request) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/jimson/server.rb', line 63

def validate_request(request)
  required_keys = %w(jsonrpc method)
  required_types = {
                     'jsonrpc' => [String],
                     'method'  => [String], 
                     'params'  => [Hash, Array],
                     'id'      => [String, Fixnum, NilClass]
                   }
  
  return false if !request.is_a?(Hash)

  required_keys.each do |key|
    return false if !request.has_key?(key)
  end

  required_types.each do |key, types|
    return false if request.has_key?(key) && !types.any? { |type| request[key].is_a?(type) }
  end

  return false if request['jsonrpc'] != JSON_RPC_VERSION
  
  true
end