Browse code
redoing some accidentally reverted changes
Showing 1 changed files
... | ... |
@@ -37,6 +37,7 @@ import copy |
37 | 37 |
import time |
38 | 38 |
import itertools |
39 | 39 |
import jsonrpc.jsonutil |
40 |
+import json |
|
40 | 41 |
|
41 | 42 |
# Twisted imports |
42 | 43 |
from twisted.web import server |
... | ... |
@@ -55,8 +56,15 @@ class ServerEvents(object): |
55 | 56 |
self.server = jsonrpc |
56 | 57 |
|
57 | 58 |
def callmethod(self, request, method, kwargs, args, **kw): |
58 |
- '''Override to implement the methods the server will make available''' |
|
59 |
- return 'Test Result' |
|
59 |
+ '''Finds the method and calls it with the specified args''' |
|
60 |
+ method = self.findmethod(method) |
|
61 |
+ if method is None: raise MethodNotFound |
|
62 |
+ |
|
63 |
+ return method(*args, **kwargs) |
|
64 |
+ |
|
65 |
+ def findmethod(self, method): |
|
66 |
+ '''Override to allow server to define methods''' |
|
67 |
+ return lambda *a, **kw: 'Test Data' |
|
60 | 68 |
|
61 | 69 |
def processrequest(self, result, args): |
62 | 70 |
'''Override to implement custom handling of the method result and request''' |
... | ... |
@@ -66,8 +74,32 @@ class ServerEvents(object): |
66 | 74 |
'''Override to implement custom error handling''' |
67 | 75 |
pass |
68 | 76 |
|
77 |
+ def processcontent(self, content, request): |
|
78 |
+ '''Given the freshly decoded content of the request, return what content should be used''' |
|
79 |
+ return content |
|
80 |
+ |
|
81 |
+ |
|
82 |
+class ServerError(Exception): |
|
83 |
+ code = 0 |
|
84 |
+ msg = "" |
|
85 |
+ id = None |
|
69 | 86 |
|
87 |
+ def json_equivalent(self): |
|
88 |
+ return dict(jsonrpc="2.0", error=dict(code=self.code, message=self.msg), id=self.id) |
|
89 |
+ def __str__(self): |
|
90 |
+ return jsonrpc.jsonutil.encode(self) |
|
70 | 91 |
|
92 |
+class InvalidRequest(ServerError): |
|
93 |
+ code = -32600 |
|
94 |
+ msg = "Invalid Request." |
|
95 |
+ |
|
96 |
+class MethodNotFound(ServerError): |
|
97 |
+ code = -32601 |
|
98 |
+ msg = "Procedure not found." |
|
99 |
+ |
|
100 |
+class ParseError(ServerError): |
|
101 |
+ code = -32700 |
|
102 |
+ msg = "Parse error." |
|
71 | 103 |
|
72 | 104 |
## Base class providing a JSON-RPC 2.0 implementation with 2 customizable hooks |
73 | 105 |
class JSON_RPC(Resource): |
... | ... |
@@ -87,26 +119,34 @@ class JSON_RPC(Resource): |
87 | 119 |
self.customize(self.eventhandler) |
88 | 120 |
Resource.__init__(self,*args, **kwargs) |
89 | 121 |
|
90 |
- def _parse_data(self, content): |
|
91 |
- if content.get('jsonrpc') != '2.0': raise ValueError, 'wrong JSON-RPC version' |
|
92 |
- method = content.get('method') |
|
93 |
- kwargs = content.get('params', {}) |
|
94 |
- args = () |
|
95 |
- if not isinstance(kwargs, dict): |
|
96 |
- args = tuple(kwargs) |
|
97 |
- kwargs = {} |
|
98 |
- else: |
|
99 |
- args = kwargs.pop('__args', args) |
|
100 |
- kwargs = dict( (str(k), v) for k,v in kwargs.items() ) |
|
101 |
- return method, kwargs, args |
|
122 |
+ |
|
123 |
+ def render(self, request): |
|
124 |
+ #move to emen2 event handler |
|
125 |
+ #ctxid = request.getCookie("ctxid") or request.args.get("ctxid", [None])[0] |
|
126 |
+ #host = request.getClientIP() |
|
127 |
+ |
|
128 |
+ request.content.seek(0, 0) |
|
129 |
+ try: |
|
130 |
+ try: |
|
131 |
+ content = jsonrpc.jsonutil.decode(request.content.read()) |
|
132 |
+ except ValueError: raise ParseError |
|
133 |
+ content = self.eventhandler.processcontent(content, request) |
|
134 |
+ d = threads.deferToThread(self._action, request, content) |
|
135 |
+ d.addCallback(self._cbRender, request) |
|
136 |
+ d.addErrback(self._ebRender, request, content.get('id') if hasattr(content, 'get') else None) |
|
137 |
+ except BaseException, e: |
|
138 |
+ self._ebRender(e, request, None) |
|
139 |
+ |
|
140 |
+ return server.NOT_DONE_YET |
|
102 | 141 |
|
103 | 142 |
|
104 | 143 |
def _cbRender(self, result, request): |
105 |
- request.setHeader("content-type", 'application/json') |
|
106 |
- request.setResponseCode(200) |
|
107 |
- result = jsonrpc.jsonutil.encode(result).encode('utf-8') |
|
108 |
- request.setHeader("content-length", len(result)) |
|
109 |
- request.write(result) |
|
144 |
+ if result is not None: |
|
145 |
+ request.setHeader("content-type", 'application/json') |
|
146 |
+ request.setResponseCode(200) |
|
147 |
+ result = jsonrpc.jsonutil.encode(result).encode('utf-8') |
|
148 |
+ request.setHeader("content-length", len(result)) |
|
149 |
+ request.write(result) |
|
110 | 150 |
request.finish() |
111 | 151 |
|
112 | 152 |
def _ebRender(self, result, request, id, finish=True): |
... | ... |
@@ -127,70 +167,69 @@ class JSON_RPC(Resource): |
127 | 167 |
request.write(result) |
128 | 168 |
if finish: request.finish() |
129 | 169 |
|
170 |
+ def _parse_data(self, content): |
|
171 |
+ if content.get('jsonrpc') != '2.0': raise InvalidRequest |
|
130 | 172 |
|
131 |
- def get_result(method_result, content, template): |
|
132 |
- template['error'].update( |
|
133 |
- code=0, |
|
134 |
- message=cgi.escape(' '.join(str(x) for x in method_result.value)), |
|
135 |
- data=content |
|
136 |
- ) |
|
137 |
- template['id'] = content.get(id) |
|
138 |
- return template |
|
139 |
- |
|
173 |
+ method = content.get('method') |
|
174 |
+ if not isinstance(method, (str, unicode)): raise InvalidRequest |
|
140 | 175 |
|
176 |
+ kwargs = content.get('params', {}) |
|
177 |
+ args = () |
|
178 |
+ if not isinstance(kwargs, dict): |
|
179 |
+ args = tuple(kwargs) |
|
180 |
+ kwargs = {} |
|
181 |
+ else: |
|
182 |
+ args = kwargs.pop('__args', args) |
|
183 |
+ kwargs = dict( (str(k), v) for k,v in kwargs.items() ) |
|
141 | 184 |
|
142 |
- def render(self, request): |
|
143 |
- ctxid = request.getCookie("ctxid") or request.args.get("ctxid", [None])[0] |
|
144 |
- host = request.getClientIP() |
|
185 |
+ return method, kwargs, args |
|
145 | 186 |
|
146 |
- request.content.seek(0, 0) |
|
147 |
- try: |
|
148 |
- content = jsonrpc.jsonutil.decode(request.content.read()) |
|
149 |
- d = threads.deferToThread(self._action, request, content, ctxid=ctxid, host=host) |
|
150 |
- d.addCallback(self._cbRender, request) |
|
151 |
- d.addErrback(self._ebRender, request, content.get('id') if hasattr(content, 'get') else None) |
|
152 |
- except BaseException, e: |
|
153 |
- self._ebRender(e, request, None) |
|
154 | 187 |
|
155 |
- return server.NOT_DONE_YET |
|
156 | 188 |
|
157 | 189 |
def render_error(self, e, id): |
158 |
- err = dict( |
|
159 |
- jsonrpc='2.0', |
|
160 |
- id = id, |
|
161 |
- error= dict( |
|
162 |
- code=0, |
|
163 |
- message=str(e), |
|
164 |
- data = e.args |
|
165 |
- )) |
|
190 |
+ if isinstance(e, ServerError): |
|
191 |
+ e.id = id |
|
192 |
+ err = e.json_equivalent() |
|
193 |
+ else: |
|
194 |
+ err = dict( |
|
195 |
+ jsonrpc='2.0', |
|
196 |
+ id = id, |
|
197 |
+ error= dict( |
|
198 |
+ code=0, |
|
199 |
+ message=str(e), |
|
200 |
+ data = e.args |
|
201 |
+ )) |
|
202 |
+ |
|
166 | 203 |
return err |
167 | 204 |
|
168 | 205 |
|
169 | 206 |
|
170 |
- def _action(self, request, contents, **kw): |
|
207 |
+ def _action(self, request, contents): |
|
171 | 208 |
result = [] |
172 | 209 |
ol = (True if isinstance(contents, list) else False) |
173 |
- if not ol: |
|
174 |
- contents = [contents] |
|
210 |
+ if not ol: contents = [contents] |
|
211 |
+ |
|
212 |
+ if contents == []: raise InvalidRequest |
|
175 | 213 |
|
176 | 214 |
for content in contents: |
177 | 215 |
try: |
178 |
- res = dict( |
|
179 |
- jsonrpc = '2.0', |
|
180 |
- id = content.get('id'), |
|
181 |
- result = self.eventhandler.callmethod(request, *self._parse_data(content), **kw) |
|
182 |
- ) |
|
216 |
+ res = dict(jsonrpc='2.0', id=content.get('id'), result=self.eventhandler.callmethod(request, *self._parse_data(content))) |
|
183 | 217 |
|
184 | 218 |
res = self.eventhandler.processrequest(res, request.args) |
185 | 219 |
|
186 |
- result.append(res) |
|
220 |
+ if res['id'] is not None: result.append(res) |
|
187 | 221 |
except Exception, e: |
188 | 222 |
err = self.render_error(e, content.get('id')) |
189 |
- result.append(err) |
|
223 |
+ if err['id'] is not None: result.append(err) |
|
224 |
+ |
|
190 | 225 |
|
191 | 226 |
|
192 | 227 |
self.eventhandler.log(result, request) |
193 | 228 |
|
194 |
- return ( result if ol else result[0] ) |
|
229 |
+ if result != []: |
|
230 |
+ if not ol: result = result[0] |
|
231 |
+ else: result = None |
|
232 |
+ |
|
233 |
+ return result |
|
195 | 234 |
|
196 | 235 |
|