Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar_network/request.py
diff options
context:
space:
mode:
Diffstat (limited to 'sugar_network/request.py')
-rw-r--r--sugar_network/request.py107
1 files changed, 107 insertions, 0 deletions
diff --git a/sugar_network/request.py b/sugar_network/request.py
new file mode 100644
index 0000000..0ca92d1
--- /dev/null
+++ b/sugar_network/request.py
@@ -0,0 +1,107 @@
+# Copyright (C) 2012, Aleksey Lim
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import json
+import logging
+import hashlib
+from gettext import gettext as _
+
+import requests
+from M2Crypto import DSA
+
+from sugar_network import env, sugar
+
+
+_logger = logging.getLogger('client')
+_headers = {}
+
+
+class ServerError(Exception):
+
+ def __init__(self, request_, error):
+ self.request = request_
+ Exception.__init__(self, error)
+
+
+def request(method, path, data=None, headers=None, **kwargs):
+ response = raw_request(method, path, data, headers, **kwargs)
+ if response.headers.get('Content-Type') == 'application/json':
+ return json.loads(response.content)
+ else:
+ return response
+
+
+def raw_request(method, path, data=None, headers=None, **kwargs):
+ path = '/'.join([i.strip('/') for i in [env.api_url.value] + path])
+
+ if not _headers:
+ uid = sugar.guid()
+ _headers['sugar_user'] = uid
+ _headers['sugar_user_signature'] = _sign(uid)
+ if headers:
+ headers.update(_headers)
+ else:
+ headers = _headers
+
+ if data is not None and headers.get('Content-Type') == 'application/json':
+ data = json.dumps(data)
+
+ verify = True
+ if env.no_check_certificate.value:
+ verify = False
+ elif env.certfile.value:
+ verify = env.certfile.value
+
+ while True:
+ try:
+ response = requests.request(method, path, data=data, verify=verify,
+ headers=headers, config={'keep_alive': True}, **kwargs)
+ except requests.exceptions.SSLError:
+ _logger.warning(_('Pass --no-check-certificate ' \
+ 'to avoid SSL checks'))
+ raise
+
+ if response.status_code != 200:
+ if response.status_code == 401:
+ _register()
+ continue
+ content = response.content
+ try:
+ error = json.loads(content)
+ raise ServerError(error['request'], error['error'])
+ except ValueError:
+ _logger.debug('Got %s HTTP error for "%s" request:\n%s',
+ response.status_code, path, content)
+ response.raise_for_status()
+
+ return response
+
+
+def _register():
+ raw_request('POST', ['user'],
+ headers={'Content-Type': 'application/json'},
+ data={
+ 'nickname': sugar.nickname() or '',
+ 'color': sugar.color() or '#000000,#000000',
+ 'machine_sn': sugar.machine_sn() or '',
+ 'machine_uuid': sugar.machine_uuid() or '',
+ 'pubkey': sugar.pubkey(),
+ },
+ )
+
+
+def _sign(data):
+ key = DSA.load_key(sugar.profile_path('owner.key'))
+ return key.sign_asn1(hashlib.sha1(data).digest()).encode('hex')