__init__.py
6.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import logging
from pyramid.httpexceptions import HTTPForbidden
from pyramid.httpexceptions import HTTPNotFound
from pyramid.renderers import null_renderer
from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid_rpc.jsonrpc import (JsonRpcError, JsonRpcMethodNotFound, JsonRpcParamsInvalid,
JsonRpcInternalError, make_error_response, MethodPredicate, BatchedRequestPredicate,
jsonrpc_renderer, add_jsonrpc_method,
DEFAULT_RENDERER,
batched_request_view, Endpoint, EndpointPredicate)
from pyramid_rpc.mapper import ViewMapperArgsInvalid, MapplyViewMapper
log = logging.getLogger(__name__)
class JsonRpcRequestForbidden(JsonRpcError):
code = -32604
message = 'request forbidden'
class JsonRpcInvalidLogin(JsonRpcError):
code = -32605
message = "Invalid User/Password"
#
# class EndpointPredicate(BaseEndpointPredicate):
# def __call__(self, info, request):
# if self.val:
# # find the endpoint info
# key = info['route'].name
# endpoint = request.registry.jsonrpc_endpoints[key]
#
# # potentially setup either rpc v1 or v2 from the parsed body
# setup_request(endpoint, request)
#
# # update request with endpoint information
# request.rpc_endpoint = endpoint
#
# # Always return True so that even if it isn't a valid RPC it
# # will fall through to the notfound_view which will still
# # return a valid JSON-RPC response.
# return True
# def setup_request(endpoint, request):
# """ Parse a JSON-RPC request body."""
# if request.method == 'GET':
# parse_request_GET(request)
# elif request.method == 'POST':
# parse_request_POST(request)
# else:
# log.debug('unsupported request method "%s"', request.method)
# raise JsonRpcRequestInvalid
#
# if hasattr(request, 'batched_rpc_requests'):
# log.debug('handling batched rpc request')
# # the checks below will look at the subrequests
# return
#
# if request.rpc_version != '2.0':
# log.debug('id:%s invalid rpc version %s',
# request.rpc_id, request.rpc_version)
# raise JsonRpcRequestInvalid
#
# if request.rpc_method is None:
# log.debug('id:%s invalid rpc method', request.rpc_id)
# raise JsonRpcRequestInvalid
# env = request.environ
# if 'HTTP_TOKEN' in env:
# try:
# user_device = token_auth(request)
# user = user_device.user
# headers = remember(request, user.id)
# request.headers["Cookie"] = dict(headers)["Set-Cookie"]
# request.headers["token"]=user_device.token
# log.debug(request.headers["Cookie"])
# except JsonRpcInvalidLoginError as e:
# raise JsonRpcInvalidLogin
#
# elif ('HTTP_USERID' in env and 'HTTP_SIGNATURE' in env and
# 'HTTP_KEY' in env):
# try:
# user = rpc_auth(request)
# headers = remember(request, user.id)
# request.headers["Cookie"] = dict(headers)["Set-Cookie"]
# log.debug(request.headers["Cookie"])
# except JsonRpcInvalidLoginError as e:
# raise JsonRpcInvalidLogin
# log.debug('handling id:%s method:%s',
# request.rpc_id, request.rpc_method)
def exception_view(exc, request):
rpc_id = getattr(request, 'rpc_id', None)
if isinstance(exc, JsonRpcError):
fault = exc
log.debug('json-rpc error rpc_id:%s "%s"',
rpc_id, exc.message)
elif isinstance(exc, HTTPNotFound):
fault = JsonRpcMethodNotFound()
log.debug('json-rpc method not found rpc_id:%s "%s"',
rpc_id, request.rpc_method)
elif isinstance(exc, HTTPForbidden):
fault = JsonRpcRequestForbidden()
log.debug('json-rpc method forbidden rpc_id:%s "%s"',
rpc_id, request.rpc_method)
elif isinstance(exc, ViewMapperArgsInvalid):
fault = JsonRpcParamsInvalid()
log.debug('json-rpc invalid method params')
else:
fault = JsonRpcInternalError()
log.exception('json-rpc exception rpc_id:%s "%s"', rpc_id, exc)
return make_error_response(request, fault, rpc_id)
def add_jsonrpc_endpoint(config, name, *args, **kw):
"""Add an endpoint for handling JSON-RPC.
``name``
The name of the endpoint.
``default_mapper``
A default view mapper that will be passed as the ``mapper``
argument to each of the endpoint's methods.
``default_renderer``
A default renderer that will be passed as the ``renderer``
argument to each of the endpoint's methods. This should be the
string name of the renderer, registered via
:meth:`pyramid.config.Configurator.add_renderer`.
A JSON-RPC method also accepts all of the arguments supplied to
:meth:`pyramid.config.Configurator.add_route`.
"""
default_mapper = kw.pop('default_mapper', MapplyViewMapper)
default_renderer = kw.pop('default_renderer', DEFAULT_RENDERER)
endpoint = Endpoint(
name,
default_mapper=default_mapper,
default_renderer=default_renderer,
)
config.registry.jsonrpc_endpoints[name] = endpoint
kw['jsonrpc_endpoint'] = True
config.add_route(name, *args, **kw)
kw = {}
kw['jsonrpc_batched'] = True
kw['renderer'] = null_renderer
config.add_view(batched_request_view, route_name=name,
permission=NO_PERMISSION_REQUIRED, **kw)
config.add_view(exception_view, route_name=name, context=Exception,
permission=NO_PERMISSION_REQUIRED)
def includeme(config):
""" Set up standard configurator registrations. Use via:
.. code-block:: python
config = Configurator()
config.include('pyramid_rpc.jsonrpc')
Once this function has been invoked, two new directives will be
available on the configurator:
- ``add_jsonrpc_endpoint``: Add an endpoint for handling JSON-RPC.
- ``add_jsonrpc_method``: Add a method to a JSON-RPC endpoint.
"""
if not hasattr(config.registry, 'jsonrpc_endpoints'):
config.registry.jsonrpc_endpoints = {}
config.add_view_predicate('jsonrpc_method', MethodPredicate)
config.add_view_predicate('jsonrpc_batched', BatchedRequestPredicate)
config.add_route_predicate('jsonrpc_endpoint', EndpointPredicate)
config.add_renderer(DEFAULT_RENDERER, jsonrpc_renderer)
config.add_directive('add_jsonrpc_endpoint', add_jsonrpc_endpoint)
config.add_directive('add_jsonrpc_method', add_jsonrpc_method)
config.add_view(exception_view, context=JsonRpcError,
permission=NO_PERMISSION_REQUIRED)