Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic server address:port for the client websocket #508

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</h2>

<p align="center" style="white-space:pre">
Remi is a GUI library for Python applications that gets rendered in web browsers.
Remi is a GUI library for Python applications that gets rendered in web browsers.
This allows you to access your interface locally and remotely.
</p>

Expand Down Expand Up @@ -166,7 +166,7 @@ Run the script. If it's all OK the GUI will be opened automatically in your brow
You can customize optional parameters in the `start` call like:

```py
start(MyApp, address='127.0.0.1', port=8081, multiple_instance=False, enable_file_cache=True, update_interval=0.1, start_browser=True)
start(MyApp, address='127.0.0.1', port=8081, multiple_instance=False, enable_file_cache=True, update_interval=0.1, start_browser=True, dynamic_web_address=True)
```

Parameters:
Expand All @@ -184,6 +184,8 @@ Additional Parameters:
- certfile: SSL certificate filename
- keyfile: SSL key file
- ssl_version: authentication version (i.e. ssl.PROTOCOL_TLSv1_2). If None disables SSL encryption
- dynamic_web_address: set it to `True` if the server is not aware of the IP address and the URL the user will be opening the app with.
If so, the JavaScript code will use hostname and port in the browser. This parameter is `False` by default.

All widgets constructors accept two standards**kwargs that are:
- width: can be expressed as int (and is interpreted as a pixel) or as str (and you can specify the measuring unit like '10%')
Expand Down Expand Up @@ -312,9 +314,10 @@ Remote access
===
If you are using your REMI app remotely, with a DNS and behind a firewall, you can specify special parameters in the `start` call:
- **port**: HTTP server port. Don't forget to NAT this port on your router;
- **dynamic_web_address**: set to `True` if the JavaScript code should use the actual URL's host and port for connecting back to the app, instead of provided IP address. This parameter is `False` by default.

```py
start(MyApp, address='0.0.0.0', port=8081)
start(MyApp, address='0.0.0.0', port=8081, dynamic_web_address=True)
```


Expand Down
12 changes: 11 additions & 1 deletion remi/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,17 @@ def set_internal_js(self, app_identifier, net_interface_ip, pending_messages_que

var self = this;
try{
this._ws = new WebSocket(ws_wss + '://%(host)s/');
host = '%(host)s'
if (host !== ''){
wss_url = `${ws_wss}://${host}/`
}
else{
host = document.location.host;
pathname = document.location.pathname;
wss_url = `${ws_wss}://${document.location.host}${pathname}`;
}

this._ws = new WebSocket(wss_url);
console.debug('opening websocket');

this._ws.onopen = function(evt){
Expand Down
19 changes: 12 additions & 7 deletions remi/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,8 @@ def _instance(self):
self._need_update_flag = client._need_update_flag
if hasattr(client, '_update_thread'):
self._update_thread = client._update_thread
net_interface_ip = self._net_interface_ip()

net_interface_ip = self._net_interface_ip() if not self.server.dynamic_web_address else ''
websocket_timeout_timer_ms = str(self.server.websocket_timeout_timer_ms)
pending_messages_queue_length = str(self.server.pending_messages_queue_length)
self.page.children['head'].set_internal_js(str(id(self)), net_interface_ip, pending_messages_queue_length, websocket_timeout_timer_ms)
Expand Down Expand Up @@ -794,7 +794,9 @@ class ThreadedHTTPServer(socketserver.ThreadingMixIn, HTTPServer):
def __init__(self, server_address, RequestHandlerClass,
auth, multiple_instance, enable_file_cache, update_interval,
websocket_timeout_timer_ms, pending_messages_queue_length,
title, server_starter_instance, certfile, keyfile, ssl_version, *userdata):
title, server_starter_instance, certfile, keyfile, ssl_version,
dynamic_web_address,
*userdata):
HTTPServer.__init__(self, server_address, RequestHandlerClass)
self.auth = auth
self.multiple_instance = multiple_instance
Expand All @@ -804,6 +806,7 @@ def __init__(self, server_address, RequestHandlerClass,
self.pending_messages_queue_length = pending_messages_queue_length
self.title = title
self.server_starter_instance = server_starter_instance
self.dynamic_web_address = dynamic_web_address
self.userdata = userdata

self.certfile = certfile
Expand All @@ -817,8 +820,8 @@ class Server(object):
# noinspection PyShadowingNames
def __init__(self, gui_class, title='', start=True, address='127.0.0.1', port=0, username=None, password=None,
multiple_instance=False, enable_file_cache=True, update_interval=0.1, start_browser=True,
websocket_timeout_timer_ms=1000, pending_messages_queue_length=1000,
certfile=None, keyfile=None, ssl_version=None, userdata=()):
websocket_timeout_timer_ms=1000, pending_messages_queue_length=1000,
certfile=None, keyfile=None, ssl_version=None, userdata=(), dynamic_web_address=False):

self._gui = gui_class
self._title = title or gui_class.__name__
Expand All @@ -837,6 +840,7 @@ def __init__(self, gui_class, title='', start=True, address='127.0.0.1', port=0,
self._keyfile = keyfile
self._ssl_version = ssl_version
self._userdata = userdata
self._dynamic_web_address = dynamic_web_address
if username and password:
self._auth = base64.b64encode(encode_text("%s:%s" % (username, password)))
else:
Expand Down Expand Up @@ -866,8 +870,9 @@ def start(self):
self._sserver = ThreadedHTTPServer((self._address, self._sport), self._gui, self._auth,
self._multiple_instance, self._enable_file_cache,
self._update_interval, self._websocket_timeout_timer_ms,
self._pending_messages_queue_length, self._title,
self, self._certfile, self._keyfile, self._ssl_version, *self._userdata)
self._pending_messages_queue_length, self._title,
self, self._certfile, self._keyfile, self._ssl_version, self._dynamic_web_address,
*self._userdata)
shost, sport = self._sserver.socket.getsockname()[:2]
self._log.info('Started httpserver http://%s:%s/'%(shost,sport))
# when listening on multiple net interfaces the browsers connects to localhost
Expand Down