~ubuntu-branches/debian/sid/bitcoin/sid

« back to all changes in this revision

Viewing changes to qa/rpc-tests/test_framework/authproxy.py

  • Committer: Package Import Robot
  • Author(s): Scott Howard
  • Date: 2015-07-29 15:45:52 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20150729154552-p5t8q38o0ekh1f09
Tags: 0.11.0-1
* New upstream release (Closes: #793622)
  - build on all archs, big endian is now supported
* Updated symbols file
* Added bitcoin-cli.1 manpage from contrib/debian/manpages
* Updated debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
"""
 
3
  Copyright 2011 Jeff Garzik
 
4
 
 
5
  AuthServiceProxy has the following improvements over python-jsonrpc's
 
6
  ServiceProxy class:
 
7
 
 
8
  - HTTP connections persist for the life of the AuthServiceProxy object
 
9
    (if server supports HTTP/1.1)
 
10
  - sends protocol 'version', per JSON-RPC 1.1
 
11
  - sends proper, incrementing 'id'
 
12
  - sends Basic HTTP authentication headers
 
13
  - parses all JSON numbers that look like floats as Decimal
 
14
  - uses standard Python json lib
 
15
 
 
16
  Previous copyright, from python-jsonrpc/jsonrpc/proxy.py:
 
17
 
 
18
  Copyright (c) 2007 Jan-Klaas Kollhof
 
19
 
 
20
  This file is part of jsonrpc.
 
21
 
 
22
  jsonrpc is free software; you can redistribute it and/or modify
 
23
  it under the terms of the GNU Lesser General Public License as published by
 
24
  the Free Software Foundation; either version 2.1 of the License, or
 
25
  (at your option) any later version.
 
26
 
 
27
  This software is distributed in the hope that it will be useful,
 
28
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
30
  GNU Lesser General Public License for more details.
 
31
 
 
32
  You should have received a copy of the GNU Lesser General Public License
 
33
  along with this software; if not, write to the Free Software
 
34
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
35
"""
 
36
 
 
37
try:
 
38
    import http.client as httplib
 
39
except ImportError:
 
40
    import httplib
 
41
import base64
 
42
import decimal
 
43
import json
 
44
import logging
 
45
try:
 
46
    import urllib.parse as urlparse
 
47
except ImportError:
 
48
    import urlparse
 
49
 
 
50
USER_AGENT = "AuthServiceProxy/0.1"
 
51
 
 
52
HTTP_TIMEOUT = 30
 
53
 
 
54
log = logging.getLogger("BitcoinRPC")
 
55
 
 
56
class JSONRPCException(Exception):
 
57
    def __init__(self, rpc_error):
 
58
        Exception.__init__(self)
 
59
        self.error = rpc_error
 
60
 
 
61
 
 
62
def EncodeDecimal(o):
 
63
    if isinstance(o, decimal.Decimal):
 
64
        return round(o, 8)
 
65
    raise TypeError(repr(o) + " is not JSON serializable")
 
66
 
 
67
class AuthServiceProxy(object):
 
68
    __id_count = 0
 
69
 
 
70
    def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None):
 
71
        self.__service_url = service_url
 
72
        self.__service_name = service_name
 
73
        self.__url = urlparse.urlparse(service_url)
 
74
        if self.__url.port is None:
 
75
            port = 80
 
76
        else:
 
77
            port = self.__url.port
 
78
        (user, passwd) = (self.__url.username, self.__url.password)
 
79
        try:
 
80
            user = user.encode('utf8')
 
81
        except AttributeError:
 
82
            pass
 
83
        try:
 
84
            passwd = passwd.encode('utf8')
 
85
        except AttributeError:
 
86
            pass
 
87
        authpair = user + b':' + passwd
 
88
        self.__auth_header = b'Basic ' + base64.b64encode(authpair)
 
89
 
 
90
        if connection:
 
91
            # Callables re-use the connection of the original proxy
 
92
            self.__conn = connection
 
93
        elif self.__url.scheme == 'https':
 
94
            self.__conn = httplib.HTTPSConnection(self.__url.hostname, port,
 
95
                                                  None, None, False,
 
96
                                                  timeout)
 
97
        else:
 
98
            self.__conn = httplib.HTTPConnection(self.__url.hostname, port,
 
99
                                                 False, timeout)
 
100
 
 
101
    def __getattr__(self, name):
 
102
        if name.startswith('__') and name.endswith('__'):
 
103
            # Python internal stuff
 
104
            raise AttributeError
 
105
        if self.__service_name is not None:
 
106
            name = "%s.%s" % (self.__service_name, name)
 
107
        return AuthServiceProxy(self.__service_url, name, connection=self.__conn)
 
108
 
 
109
    def __call__(self, *args):
 
110
        AuthServiceProxy.__id_count += 1
 
111
 
 
112
        log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self.__service_name,
 
113
                                 json.dumps(args, default=EncodeDecimal)))
 
114
        postdata = json.dumps({'version': '1.1',
 
115
                               'method': self.__service_name,
 
116
                               'params': args,
 
117
                               'id': AuthServiceProxy.__id_count}, default=EncodeDecimal)
 
118
        self.__conn.request('POST', self.__url.path, postdata,
 
119
                            {'Host': self.__url.hostname,
 
120
                             'User-Agent': USER_AGENT,
 
121
                             'Authorization': self.__auth_header,
 
122
                             'Content-type': 'application/json'})
 
123
 
 
124
        response = self._get_response()
 
125
        if response['error'] is not None:
 
126
            raise JSONRPCException(response['error'])
 
127
        elif 'result' not in response:
 
128
            raise JSONRPCException({
 
129
                'code': -343, 'message': 'missing JSON-RPC result'})
 
130
        else:
 
131
            return response['result']
 
132
 
 
133
    def _batch(self, rpc_call_list):
 
134
        postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal)
 
135
        log.debug("--> "+postdata)
 
136
        self.__conn.request('POST', self.__url.path, postdata,
 
137
                            {'Host': self.__url.hostname,
 
138
                             'User-Agent': USER_AGENT,
 
139
                             'Authorization': self.__auth_header,
 
140
                             'Content-type': 'application/json'})
 
141
 
 
142
        return self._get_response()
 
143
 
 
144
    def _get_response(self):
 
145
        http_response = self.__conn.getresponse()
 
146
        if http_response is None:
 
147
            raise JSONRPCException({
 
148
                'code': -342, 'message': 'missing HTTP response from server'})
 
149
 
 
150
        responsedata = http_response.read().decode('utf8')
 
151
        response = json.loads(responsedata, parse_float=decimal.Decimal)
 
152
        if "error" in response and response["error"] is None:
 
153
            log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal)))
 
154
        else:
 
155
            log.debug("<-- "+responsedata)
 
156
        return response