diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2014-05-06 15:45:23 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2014-05-06 15:45:23 (GMT) |
commit | 5ebeca1a965aa4028fde7a73c7baffbdba705ef5 (patch) | |
tree | 6f235294538de709cce4809bc2bbfbff4c396b3c | |
parent | 0684b55b5f66da1c2dc61f15105ef5e0632019bf (diff) |
Support HTTP connection via UNIX domain sockets
m--------- | sugar_network/lib/requests | 0 | ||||
-rw-r--r-- | sugar_network/toolkit/coroutine.py | 33 | ||||
-rw-r--r-- | sugar_network/toolkit/http.py | 8 | ||||
-rwxr-xr-x | tests/units/toolkit/http.py | 26 |
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() |