forked from joshmarshall/jsonrpctcp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
221 lines (172 loc) · 7.19 KB
/
README
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
JSONRPCTCP
==========
This project is just an implementation of the JSON-RPC protocol over
TCP. It supports the JSON-RPC 2.0 specification, but it is not (at
this point) backwards-compatible with 1.0, because I like 2.0 more. :)
It also supports basic encryption and decryption via pycrypto if it is
installed. Alternatively, you can wrap your own cipher class as long
as it utilizes the 'new', 'encrypt', and 'decrypt' methods in the same
manner as the Crypto.Cipher classes in the pycrypto library.
It's early on, so feedback is greatly desired. You can hit the
Google Groups site at http://groups.google.com/group/jsonrpctcp or
email jsonrpctcp@googlegroups.com if you have any questions, advice,
patches, or just need a friend. :)
JSONRPCTCP is licensed under the Apache Licence, Version 2.0
(http://www.apache.org/licenses/LICENSE-2.0.html).
Requirements
============
* Python 2.5+
* SimpleJSON on Python < 2.6
* PyCrypto (optional) for encryption support
Installation
============
python setup.py build
sudo python setup.py install
Tests
=====
The jsonrpctcp library contains nearly-verbatim tests from the
JSON-RPC 2.0 Specification Document.
(http://groups.google.com/group/json-rpc/web/json-rpc-2-0)
After installation, or from the same directory as the setup.py
file and this README, you can run the tests like so:
python -m jsonrpctcp.tests
If all is well, you should see 13ish tests that ran successfully.
Additionally, you can spin up a test server in one terminal
and run a few test client methods in another with the following
instructions. (These tests are not as detailed, but it's there
for whatever purpose.)
Start server (hit Ctrl-C or Ctrl-Break in Windows to stop):
python -m jsonrpctcp.server
Start client in another terminal:
python -m jsonrpctcp.client
The client terminal should print out a short list of tests it
performed.
Usage Examples
==============
Below, you'll find simple uses of both client and server. I'd love
to hear feedback on the usability of this interface, and whether
certain controls / attributes should be more accessible.
Client Usage
============
This should be pretty familiar to users of xmlrpclib, with only a few
name differences. The connect method takes the IP address / machine name,
the port of the service, and an optional key if encryption is desired.
Encryption requires the pycrypto library or a cipher-like class as the
config.crypt value. See configuration info below for details.
Client examples:
# Simple example
from jsonrpctcp import connect
conn = connect('localhost', 8001)
# Optionally, you can add a third string parameter which is the
# encryption key used on the server.
conn = connect('localhost', 8001, '12345abcdef67890')
# Just use simple dot-syntax to call methods. Don't use a method
# that starts with an underscore -- those are automatically private.
result = conn.add(1, 2)
# ...and should be 3. :)
# Notification example -- it uses the '_notification' attribute
# of the client connection to flag that this request doesn't need
# a response.
conn._notification.add(5, 6)
# Null response, because it's a notification. It actually closes the
# connection after submitting the full request.
# Batch example -- it uses the '_batch' method of the client
# connection to return a new, batch-enabled connection. It
# automatically orders the reponses and skips notifications.
batch = conn._batch()
batch.add(y=5, x=6)
batch._notification.add(6,4)
batch.namespace.echo("Repeat me!")
result = batch()
for i in result:
print i
# Should print out 11, and then "Repeat me!", skipping the
# notification.
# You can access the request and response data with
# history.request and history.response . These are the
# string values after any encryption / decryption, so you'll
# need to use a JSON library to decode them.
from jsonrpctcp import history
result = conn.sum(5, 6)
print history.request
>>> {"params": [5, 6], "jsonrpc": "2.0", "method": "sum", "id":
"2fa1a919-5a14-44a8-bb52-af16757b12ee"}
print history.response
>>> {"jsonrpc": "2.0", "result": 11, "id":
"2fa1a919-5a14-44a8-bb52-af16757b12ee"}
# You can also see the responses via the logger:
from jsonrpctcp import logger
import logging
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())
result = conn.sum(5, 6)
# The following prints out:
CLIENT | REQUEST: {"params": [5, 6], "jsonrpc": "2.0", "method": "sum",
"id": "734941ad-bc30-4572-9e5f-e974fd04ef1c"}
CLIENT | RESPONSE: {"jsonrpc": "2.0", "result": 11, "id":
"734941ad-bc30-4572-9e5f-e974fd04ef1c"}
Server Usage
============
The server is bound to a socket, and the handler function(s) can be passed
in manually one by one, or (preferred) you can subclass the Handler object
and use that. It threads (not forks) the individual requests for you, but
if you don't use the start_server() shortcut, you'll have to thread the
actual server startup yourself if you want to do anything after it starts.
All you should need to enable encrypted support is pycrypto installed, and
to set the config.secret to an appropriate key string. See below for config
details.
Server examples:
# Function handler example
from jsonrpctcp.server import Server
from jsonrpctcp import config
config.verbose = True
def add(x, y):
return x+y
def echo(message):
return message
server = Server(('localhost', 8001))
server.add_handler(add)
server.add_handler(echo, 'namespace.echo')
server.serve() # blocks
------------------
# Class handler example
from jsonrpctcp import start_server
from jsonrpctcp.handler import Handler
import time
class NewHandler(Handler):
def echo(self, message):
return message
# This automatically threads the server instance.
server = start_server('localhost', 8001, NewHandler)
while True:
# Do whatever you need for polling
time.sleep(5)
# You'll have to thread the start up yourself this way, if you need it.
Configuration
=============
There's a simple configuration object that has a few attributes. You can
change them per the following:
from jsonrpctcp import config
config.verbose = True # default is False
config.timeout = 30 # default is 5
config.buffer = 4096 # default is 1024
config.crypt = DES3 # default is AES if pycrypto is installed
config.secret = '12345abcdef67890'
# default is none, 'secret' indicates that the server should
# decrypt requests and encrypt responses.
These may not be the best defaults, any thoughts would be appreciated.
Debugging
=========
If you want to see the actual requests, responses, etc. you'll need to
add a handler and set a level to the jsonrpctcp logger. This uses the
basic python logging module, so it should be fairly familiar:
import loggging
from jsonrpctcp import logger
logger.addHandler(logging.StreamHandler()) # sends to stdout
logger.setLevel(logging.DEBUG)
TODO
====
* Replace threaded socket requests with epoll / select fallback.
* Stabilize and get on PyPI.
* Add more unit tests.
* Generally make more awesome.