Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2014-05-06 15:45:23 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2014-05-06 15:45:23 (GMT)
commit5ebeca1a965aa4028fde7a73c7baffbdba705ef5 (patch)
tree6f235294538de709cce4809bc2bbfbff4c396b3c
parent0684b55b5f66da1c2dc61f15105ef5e0632019bf (diff)
Support HTTP connection via UNIX domain sockets
m---------sugar_network/lib/requests0
-rw-r--r--sugar_network/toolkit/coroutine.py33
-rw-r--r--sugar_network/toolkit/http.py8
-rwxr-xr-xtests/units/toolkit/http.py26
4 files changed, 65 insertions, 2 deletions
diff --git a/sugar_network/lib/requests b/sugar_network/lib/requests
-Subproject 41b3982ccf322223048c5d9ddecf191d2c91adf
+Subproject 48123385c4d166bc4fd5adb39a895098001c826
diff --git a/sugar_network/toolkit/coroutine.py b/sugar_network/toolkit/coroutine.py
index e3a6173..1f3d842 100644
--- a/sugar_network/toolkit/coroutine.py
+++ b/sugar_network/toolkit/coroutine.py
@@ -19,6 +19,7 @@
import os
import logging
+from os.path import dirname, exists
import gevent
from gevent import hub
@@ -79,6 +80,38 @@ def socket(*args, **kwargs):
return gevent.socket.socket(*args, **kwargs)
+def listen_unix_socket(path, backlog=5):
+ # pylint: disable-msg=E1101
+ from tempfile import NamedTemporaryFile
+ import _socket
+
+ if exists(path):
+ raise RuntimeError('The socket address is in use')
+
+ sock = socket(_socket.AF_UNIX, _socket.SOCK_STREAM)
+ sock.setblocking(0)
+
+ with NamedTemporaryFile(dir=dirname(path)) as tmp_path:
+ pass
+ sock.bind(tmp_path.name)
+ try:
+ os.rename(tmp_path.name, path)
+ except Exception, error:
+ sock.close()
+ os.unlink(tmp_path.name)
+ raise RuntimeError('Failed to create socket: %s' % error)
+ sock.listen(backlog)
+
+ def close():
+ os.unlink(path)
+ return orig_close()
+
+ orig_close = sock.close
+ sock.close = close
+
+ return sock
+
+
def gethostbyname(host):
import gevent.socket
return gevent.socket.gethostbyname(host)
diff --git a/sugar_network/toolkit/http.py b/sugar_network/toolkit/http.py
index f0e9e5e..f3c2ef8 100644
--- a/sugar_network/toolkit/http.py
+++ b/sugar_network/toolkit/http.py
@@ -112,7 +112,7 @@ class Connection(object):
def __init__(self, url='', creds=None, max_retries=0, auth_request=None,
**session_args):
- self.url = url
+ self.url = url.rstrip('/')
self.creds = creds
self._max_retries = max_retries
self._session_args = session_args
@@ -208,7 +208,11 @@ class Connection(object):
if not path:
path = ['']
if not isinstance(path, basestring):
- path = '/'.join([i.strip('/') for i in [self.url] + path])
+ path = '/'.join([i.strip('/') for i in path])
+ if self.url.startswith('file://'):
+ path = self.url + '#' + path
+ else:
+ path = self.url + '/' + path
# TODO Disable cookies on requests library level
self._session.cookies.clear()
diff --git a/tests/units/toolkit/http.py b/tests/units/toolkit/http.py
index f05da0d..14f280b 100755
--- a/tests/units/toolkit/http.py
+++ b/tests/units/toolkit/http.py
@@ -257,6 +257,32 @@ class HTTPTest(tests.Test):
], challenges)
del challenges[:]
+ def test_UnixSocket(self):
+
+ def app(environ, start_response):
+ start_response('200', [('content-type', 'application/json')])
+ yield json.dumps([
+ environ['HTTP_HOST'],
+ environ['REQUEST_METHOD'],
+ environ['PATH_INFO'],
+ environ['QUERY_STRING'],
+ json.loads(environ['wsgi.input'].read()),
+ ])
+
+ server = coroutine.WSGIServer(coroutine.listen_unix_socket('./socket'), app)
+ coroutine.spawn(server.serve_forever)
+ coroutine.dispatch()
+
+ conn = http.Connection('file://socket')
+ self.assertEqual([
+ 'localhost',
+ 'POST',
+ '/path/subpath',
+ 'foo=bar',
+ 'payload',
+ ],
+ conn.post(['path', 'subpath'], 'payload', foo='bar'))
+
if __name__ == '__main__':
tests.main()