Unverified Commit b3c2ca2f authored by Jeremy Tuloup's avatar Jeremy Tuloup Committed by GitHub
Browse files

Merge pull request #75 from bollwyvl/gh-73-fix-node-serving-classic

Fix node dev server for unslashed endpoints, vanity try URLs on docs, fix binder
parents cce62f53 d4f637bd
......@@ -5,11 +5,13 @@ channels:
- conda-forge
dependencies:
# build stuff
- black
- flit >=3.1
# demo stuff
- jupyter-server-proxy
- jupyterlab >=3,<4
- jupyterlab-classic
- git
# extra docs tools
- sphinx-autobuild
......@@ -28,4 +30,5 @@ dependencies:
- pydata-sphinx-theme
- pytest-check-links
- sphinx
- sphinxext-rediraffe
### DOCS ENV ###
......@@ -17,11 +17,11 @@ from the ground-up using JupyterLab components and plugins.
JupyterLite works with both [JupyterLab](https://github.com/jupyterlab/jupyterlab) and
[JupyterLab Classic](https://github.com/jtpio/jupyterlab-classic).
### [Try it with JupyterLab!](https://jupyterlite.readthedocs.io/en/latest/_static/lab/index.html)
### [Try it with JupyterLab!](https://jupyterlite.readthedocs.io/en/latest/try/lab)
![image](https://user-images.githubusercontent.com/591645/114009512-7fe79600-9863-11eb-9aac-3a9ef6345011.png)
### [Try it with JupyterLab Classic!](https://jupyterlite.readthedocs.io/en/latest/_static/classic/index.html)
### [Try it with JupyterLab Classic!](https://jupyterlite.readthedocs.io/en/latest/try/classic)
![image](https://user-images.githubusercontent.com/591645/114454062-78fdb200-9bda-11eb-9cda-4ee327dd1c77.png)
......
......@@ -6,7 +6,7 @@
(function() {
window.location.href = window.location.href.replace(
/\/tree(\/|\/index.html)?$/,
'/../classic/tree/index.html'
'/classic/tree/index.html'
);
}.call(this));
</script>
......
......@@ -23,6 +23,7 @@ version = ".".join(release.rsplit(".", 1))
# sphinx config
extensions = [
"sphinx.ext.autosectionlabel",
"sphinxext.rediraffe",
"myst_nb",
]
......@@ -30,6 +31,12 @@ autosectionlabel_prefix_document = True
myst_heading_anchors = 3
suppress_warnings = ["autosectionlabel.*"]
rediraffe_redirects = {
"try/index": "_static/index",
"try/lab/index": "_static/lab/index",
"try/classic/index": "_static/classic/tree/index",
}
# files
templates_path = ["_templates"]
html_favicon = "../app/lab/favicon.ico"
......
......@@ -21,4 +21,5 @@ dependencies:
- pydata-sphinx-theme
- pytest-check-links
- sphinx
- sphinxext-rediraffe
### DOCS ENV ###
......@@ -297,9 +297,11 @@ class L:
ALL_JSON = set(
[*P.PACKAGE_JSONS, *P.APP_JSONS, P.ROOT_PACKAGE_JSON, *P.ROOT.glob("*.json")]
)
ALL_JS = [*(P.ROOT / "scripts").glob("*.js"), *(P.APP).glob("*/index.js")]
ALL_HTML = [(P.APP / "index.html"), *P.APP.glob("*/index.html")]
ALL_MD = [*P.CI.rglob("*.md"), *P.DOCS_MD]
ALL_YAML = [*P.ROOT.glob("*.yml"), *P.BINDER.glob("*.yml"), *P.CI.rglob("*.yml")]
ALL_PRETTIER = [*ALL_JSON, *ALL_MD, *ALL_YAML, *ALL_ESLINT]
ALL_PRETTIER = [*ALL_JSON, *ALL_MD, *ALL_YAML, *ALL_ESLINT, *ALL_JS, *ALL_HTML]
ALL_BLACK = [
*P.DOCS_PY,
P.DODO,
......
......@@ -5,3 +5,4 @@ myst-nb
pydata-sphinx-theme
pytest-check-links
sphinx
sphinxext-rediraffe
......@@ -10,14 +10,18 @@ const DO_NOT_USE_THIS = `
********************************************************************************
`;
const http = require('http');
const fs = require('fs');
const fs = require('fs/promises');
const path = require('path');
const { resolve } = require('path');
const ROOT = path.resolve(__dirname, '..', 'app');
const HOST = process.env['HOST'] || '127.0.0.1';
const PORT = parseInt(process.env['PORT'] || '5000');
const PREFIX = process.env['PREFIX'] || '/';
const ERRORS = { ENOENT: 404 };
const CUSTOM_ROUTES = {
'/favicon.ico': '/lab/favicon.ico'
};
const MIME_TYPES = {
// from https://github.com/python/cpython/blob/3.9/Lib/mimetypes.py
......@@ -169,22 +173,55 @@ const MIME_TYPES = {
'.data': 'application/wasm'
};
function serve(request, response) {
function stripSlash(url) {
return url.replace(/\/$/, '');
}
async function serve(request, response) {
let { url, method } = request;
url = `${url.slice(PREFIX.length - 1)}`;
url = url.endsWith('/') ? `${url}index.html` : url;
fs.readFile(path.join(ROOT, url), function(error, content) {
const code = error ? ERRORS[error.code] || 500 : 200;
console.error(new Date().toISOString(), code, method, url);
if (code === 200) {
mime = MIME_TYPES[`${path.extname(url)}`] || 'application/octet-stream';
} else {
content = `<h1>${code}</h1>`;
mime = 'text/html';
}
let code = 500;
let mime = 'application/octet-stream';
let content = '<h1><pre>500 Really Unexpected Error</pre></h1>';
url = stripSlash(`${url.slice(PREFIX.length - 1)}`);
url = CUSTOM_ROUTES[url] || url;
let resolved = path.join(ROOT, url);
let exists = false;
let isDirectory = false;
try {
let stat = await fs.stat(resolved);
exists = true;
isDirectory = stat.isDirectory();
} catch (error) {
// will attempt to find index.html
}
if (exists && isDirectory) {
url = [url, 'index.html'].join('/');
resolved = path.join(ROOT, url);
}
let extname = path.extname(url);
try {
content = await fs.readFile(resolved);
mime = MIME_TYPES[extname] || mime;
code = 200;
} catch (error) {
code = ERRORS[error.code] || code;
content = `<h1><pre>${code} ${error.code}</pre></h1>`;
mime = 'text/html';
} finally {
(code == 200 ? console.info : console.error)(
new Date().toISOString(),
code,
method,
url
);
response.writeHead(code, { 'Content-Type': mime });
response.end(content, 'utf-8');
});
}
}
http.createServer(serve).listen(PORT, HOST, () => {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment