Skip to content

Commit

Permalink
Allow configuration via traitlets
Browse files Browse the repository at this point in the history
  • Loading branch information
jwindgassen committed Jan 7, 2025
1 parent 1ff6051 commit e07a615
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
23 changes: 23 additions & 0 deletions docs/source/standalone.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,29 @@ not trigger the login process when accessing the application.
especially on multi-user systems.
```

### Configuration via traitlets

Instead of using the commandline, a standalone proxy can also be configured via a `traitlets` configuration file.
The configuration file can be loaded by running `jupyter standaloneproxy --config path/to/config.py`.

The options mentioned above can also be configured in the config file:

```python
# Specify the command to execute
c.StandaloneProxyServer.command = [
"voila", "--no-browser", "--port={port}", "/path/to/some/Notebook.ipynb"
]

# Specify address and port
c.StandaloneProxyServer.address = "localhost"
c.StandaloneProxyServer.port = 8000

# Disable authentication
c.StandaloneProxyServer.skip_authentication = True
```

A default config file can be emitted by running `jupyter standaloneproxy --generate-config`

## Usage with JupyterHub

To launch a standalone proxy with JupyterHub, you need to customize the `Spawner` inside the configuration
Expand Down
24 changes: 17 additions & 7 deletions jupyter_server_proxy/standalone/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,29 @@
from textwrap import dedent
from urllib.parse import urlparse

from jupyter_core.application import JupyterApp
from jupyterhub.services.auth import HubOAuthCallbackHandler
from jupyterhub.utils import make_ssl_context
from tornado import httpclient, httpserver, ioloop, web
from tornado.web import RedirectHandler
from traitlets.config import Application as TraitletsApplication
from traitlets.traitlets import Bool, Int, Unicode, default, validate

from ..config import ServerProcess
from .activity import start_activity_update
from .proxy import make_standalone_proxy


class StandaloneProxyServer(TraitletsApplication, ServerProcess):
class StandaloneProxyServer(JupyterApp, ServerProcess):
name = "jupyter-standalone-proxy"
description = """
Wrap an arbitrary web service so it can be used in place of 'jupyterhub-singleuser'
in a JupyterHub setting.
Usage: jupyter standaloneproxy [options] -- <command>
The <command> will be executed to start the web service once the proxy receives the first request. The command can
contain the placeholders '{{port}}', '{{unix_socket}}' and '{{base_url}}', which will be replaced with the
appropriate values once the application starts.
For more details, see the jupyter-server-proxy documentation.
"""
examples = "jupyter standaloneproxy -- voila --port={port} --no-browser /path/to/notebook.ipynb"

base_url = Unicode(
help="""
Expand Down Expand Up @@ -152,19 +149,21 @@ def __init__(self, **kwargs):
# exeptions we do not need, for easier use of the CLI
# We don't need "command" here, as we will take it from the extra_args
ignore_traits = [
"name",
"launcher_entry",
"new_browser_tab",
"rewrite_response",
"update_last_activity",
"command",
]
server_process_aliases = {
trait: f"ServerProcess.{trait}"
trait: f"StandaloneProxyServer.{trait}"
for trait in ServerProcess.class_traits(config=True)
if trait not in ignore_traits and trait not in self.flags
}

self.aliases = {
**super().aliases,
**server_process_aliases,
"base_url": "StandaloneProxyServer.base_url",
"address": "StandaloneProxyServer.address",
Expand All @@ -174,6 +173,17 @@ def __init__(self, **kwargs):
"websocket_max_message_size": "StandaloneProxyServer.websocket_max_message_size",
}

def emit_alias_help(self):
yield from super().emit_alias_help()
yield ""

# Manually yield the help for command, which we will get from extra_args
command_help = StandaloneProxyServer.class_get_trait_help(
ServerProcess.command
).split("\n")
yield command_help[0].replace("--StandaloneProxyServer.command", "command")
yield from command_help[1:]

def get_proxy_base_class(self) -> tuple[type | None, dict]:
cls, kwargs = super().get_proxy_base_class()
if cls is None:
Expand Down

0 comments on commit e07a615

Please sign in to comment.