Skip to content

Instantly share code, notes, and snippets.

@hamelin
Last active April 12, 2023 16:00
Show Gist options
  • Save hamelin/f21bd05c3216439f9089c6a05441c8a3 to your computer and use it in GitHub Desktop.
Save hamelin/f21bd05c3216439f9089c6a05441c8a3 to your computer and use it in GitHub Desktop.
Example of usage of Jupyter Proxy Server to host local content for an in-notebook GUI.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "2cf1c77f-6601-424d-a86f-4faaeb6a4683",
"metadata": {},
"source": [
"# Accessing static local content in support of an in-notebook web service\n",
"\n",
"Whenever one is developing a notebook-embedded GUI using [Jupyter widgets](https://ipywidgets.readthedocs.io/en/stable/)\n",
"or [Panel](https://panel.holoviz.org/index.html), there may arise a need to access some content present on the local filesystem within the client-side code.\n",
"This is surprisingly tricky: file URLs are a big security hole, and most browsers won't allow them from a notebook.\n",
"\n",
"A simple solution consists in proxying a static web server through the Jupyter web server.\n",
"This is made possible by the [Jupyter Server Proxy](https://jupyter-server-proxy.readthedocs.io/en/latest/) extension."
]
},
{
"cell_type": "markdown",
"id": "065efb53-771d-41a0-b5cc-fc7a48c13389",
"metadata": {},
"source": [
"## Setup"
]
},
{
"cell_type": "markdown",
"id": "195df846-f916-4439-9c6a-7fb96c6f0a12",
"metadata": {},
"source": [
"1. Create a virtual environment that includes packages `jupyterlab` and `jupyter-server-proxy`.\n",
"1. Start Jupyter Lab or Jupyter notebook as you would regularly:\n",
" ```\n",
" \n",
" jupyter lab\n",
" \n",
" \n",
" ```\n",
"1. Open and run this notebook in that Jupyter instance."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "26b73cde-7ea9-4421-bc9e-93fed50527b0",
"metadata": {},
"outputs": [],
"source": [
"from http.server import HTTPServer, SimpleHTTPRequestHandler\n",
"import threading as thr"
]
},
{
"cell_type": "markdown",
"id": "cd2f4581-6c75-4091-829e-9135740a317d",
"metadata": {},
"source": [
"Let's instantiate a new web server.\n",
"As it stands, it will simply serve content from the current directory."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "45466bf3-9e5a-4e55-86df-a88f2fa3397e",
"metadata": {},
"outputs": [],
"source": [
"server = HTTPServer((\"\", 0), SimpleHTTPRequestHandler)\n",
"server.server_address"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46dfc0ce-65d1-4b15-b60a-cd0248ef3241",
"metadata": {},
"outputs": [],
"source": [
"service = thr.Thread(target=server.serve_forever)\n",
"service.start()"
]
},
{
"cell_type": "markdown",
"id": "b437fd8f-f95b-45a4-b965-353d1c9ebedf",
"metadata": {},
"source": [
"Let's have an image to serve off of our newly minted server."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b23169ac-d7fb-4188-bf04-07a672b0c574",
"metadata": {},
"outputs": [],
"source": [
"import base64\n",
"import os\n",
"import requests as rq\n",
"\n",
"with open(\"freya-luna.jpg\", \"wb\") as file_image:\n",
" file_image.write(\n",
" base64.b64decode(\n",
" rq.get(\"https://gist.github.com/hamelin/c02285b00636705b7941b1157bf19f85/raw/f142a25a8442feaba135829d55f25cd3549f992e/freya-luna.jpg.b64\").content\n",
" )\n",
" )\n",
"os.stat(\"freya-luna.jpg\")"
]
},
{
"cell_type": "markdown",
"id": "3f900f59-7c0a-4628-8945-383bab0c93ae",
"metadata": {},
"source": [
"The following cell will generate a HTML cell that will use the browser to access an image through our proxied web server.\n",
"Run it, then run the new cell that will appear underneath."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "42d7b183-9381-41f6-b6bf-ab59d4d4c606",
"metadata": {},
"outputs": [],
"source": [
"name_image = \"freya-luna.jpg\"\n",
"get_ipython().set_next_input(f\"\"\"\n",
"%%html\n",
"<img src=\"/proxy/{server.server_address[1]}/{name_image}\">\n",
"\"\"\".strip())"
]
},
{
"cell_type": "raw",
"id": "c60149d8-f69c-484f-88b4-1e690aaf3a77",
"metadata": {},
"source": [
"%%html\n",
"<img src=\"/proxy/33743/freya-luna.jpg\">"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b92f064e-65df-4a66-9eec-64a110448867",
"metadata": {},
"outputs": [],
"source": [
"server.shutdown()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment