From fb543cea442bf91acc8d03b1dcfabdd44883229d Mon Sep 17 00:00:00 2001 From: Jonathan Curran Date: Fri, 6 Jul 2018 14:25:23 -0600 Subject: [PATCH] Utilize path in server address (#27) Previously, we were not using paths specified in the provided server address. This meant that addresses like http://server/proxied/path/to/connect would not work correctly. This fix utilizes the path if provided and uses it for every request. --- rsconnect/__init__.py | 8 ++------ rsconnect/rsconnect.py | 41 ++++++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/rsconnect/__init__.py b/rsconnect/__init__.py index 77760858..87aaf40f 100644 --- a/rsconnect/__init__.py +++ b/rsconnect/__init__.py @@ -83,7 +83,7 @@ def post(self, action): api_key = data['api_key'] title = data['notebook_title'] try: - retval = app_search(uri.scheme, uri.hostname, uri.port, api_key, title) + retval = app_search(uri, api_key, title) except RSConnectException as exc: raise web.HTTPError(400, exc.message) self.finish(json.dumps(retval)) @@ -149,11 +149,7 @@ def post(self, action): # rewind file pointer bundle.seek(0) try: - published_app = deploy( - uri.scheme, uri.hostname, uri.port, - api_key, app_id, nb_title, - bundle - ) + published_app = deploy(uri, api_key, app_id, nb_title, bundle) except RSConnectException as exc: raise web.HTTPError(400, exc.message) diff --git a/rsconnect/rsconnect.py b/rsconnect/rsconnect.py index ef182db5..41ba0d93 100644 --- a/rsconnect/rsconnect.py +++ b/rsconnect/rsconnect.py @@ -21,6 +21,7 @@ def __init__(self, message): super(RSConnectException, self).__init__(message) self.message = message +from notebook.utils import url_path_join logger = logging.getLogger('rsconnect') @@ -49,7 +50,7 @@ def verify_server(server_address): conn = http.HTTPConnection(r.hostname, port=(r.port or http.HTTP_PORT), timeout=10) else: conn = http.HTTPSConnection(r.hostname, port=(r.port or http.HTTPS_PORT), timeout=10) - conn.request('GET', '/__api__/server_settings') + conn.request('GET', url_path_join(r.path or '/', '__api__/server_settings')) response = conn.getresponse() if response.status >= 400: return False @@ -62,12 +63,13 @@ def verify_server(server_address): class RSConnect: - def __init__(self, scheme, host, api_key, port=3939): + def __init__(self, uri, api_key): + self.path_prefix = uri.path or '/' self.api_key = api_key self.conn = None - self.mk_conn = lambda: http.HTTPConnection(host, port=port, timeout=10) - if scheme == 'https': - self.mk_conn = lambda: http.HTTPSConnection(host, port=port, timeout=10) + self.mk_conn = lambda: http.HTTPConnection(uri.hostname, port=uri.port, timeout=10) + if uri.scheme == 'https': + self.mk_conn = lambda: http.HTTPSConnection(uri.hostname, port=uri.port, timeout=10) self.http_headers = { 'Authorization': 'Key %s' % self.api_key, } @@ -81,9 +83,10 @@ def __exit__(self, *args): self.conn = None def request(self, method, path, *args, **kwargs): - logger.info('Performing: %s %s' % (method, path)) + request_path = url_path_join(self.path_prefix, path) + logger.info('Performing: %s %s' % (method, request_path)) try: - self.conn.request(method, path, *args, **kwargs) + self.conn.request(method, request_path, *args, **kwargs) except http.HTTPException as e: logger.error('HTTPException: %s' % e) raise RSConnectException(str(e)) @@ -120,28 +123,28 @@ def json_response(self): return data def me(self): - self.request('GET', '/__api__/me', None, self.http_headers) + self.request('GET', '__api__/me', None, self.http_headers) return self.json_response() def app_find(self, filters): params = urlencode(filters) - self.request('GET', '/__api__/applications?' + params, None, self.http_headers) + self.request('GET', '__api__/applications?' + params, None, self.http_headers) data = self.json_response() if data['count'] > 0: return data['applications'] def app_create(self, name): params = json.dumps({'name': name}) - self.request('POST', '/__api__/applications', params, self.http_headers) + self.request('POST', '__api__/applications', params, self.http_headers) return self.json_response() def app_upload(self, app_id, tarball): - self.request('POST', '/__api__/applications/%d/upload' % app_id, tarball, self.http_headers) + self.request('POST', '__api__/applications/%d/upload' % app_id, tarball, self.http_headers) return self.json_response() def app_deploy(self, app_id, bundle_id = None): params = json.dumps({'bundle': bundle_id}) - self.request('POST', '/__api__/applications/%d/deploy' % app_id, params, self.http_headers) + self.request('POST', '__api__/applications/%d/deploy' % app_id, params, self.http_headers) return self.json_response() def app_publish(self, app_id, access): @@ -150,15 +153,15 @@ def app_publish(self, app_id, access): 'id': app_id, 'needs_config': False }) - self.request('POST', '/__api__/applications/%d' % app_id, params, self.http_headers) + self.request('POST', '__api__/applications/%d' % app_id, params, self.http_headers) return self.json_response() def app_config(self, app_id): - self.request('GET', '/__api__/applications/%d/config' % app_id, None, self.http_headers) + self.request('GET', '__api__/applications/%d/config' % app_id, None, self.http_headers) return self.json_response() def task_get(self, task_id): - self.request('GET', '/__api__/tasks/%s' % task_id, None, self.http_headers) + self.request('GET', '__api__/tasks/%s' % task_id, None, self.http_headers) return self.json_response() @@ -173,8 +176,8 @@ def mk_manifest(file_name): }) -def deploy(scheme, host, port, api_key, app_id, app_title, tarball): - with RSConnect(scheme, host, api_key, port) as api: +def deploy(uri, api_key, app_id, app_title, tarball): + with RSConnect(uri, api_key) as api: if app_id is None: # create an app if id is not provided app = api.app_create(app_title) @@ -207,8 +210,8 @@ def task_is_finished(task_id): raise RSConnectException('Failed to deploy successfully') -def app_search(scheme, host, port, api_key, app_title): - with RSConnect(scheme, host, api_key, port) as api: +def app_search(uri, api_key, app_title): + with RSConnect(uri, api_key) as api: me = api.me() filters = [('count', 5), ('filter', 'min_role:editor'),