refactor!: unify slash handling

It is hard to remember to add `/` at the end of the URL when configuring
a new etherpad URL. Also, web server proxies tend to do weird stuff when
you assume that you have a slash on the end of each URL.

So, I took a look at how to avoid doing that. It turns out that both
urljoin / os.path.join are kinda bad for handling URL building. Also,
APPLICATION_ROOT didn't seem that necessary since Flask knows what to do
with a `/` at the start of a URL, so I dropped it.

I think this doesn't break anything!
This commit is contained in:
decentral1se 2022-10-02 16:51:12 +02:00
parent 8b4d0905e2
commit 42e408859b
No known key found for this signature in database
GPG Key ID: 03789458B3D0C410
6 changed files with 49 additions and 48 deletions

View File

@ -1,6 +1,6 @@
import os import os
import json import json
from flask import Flask, request, render_template, redirect, url_for from flask import Flask, request, render_template, redirect
from urllib.request import urlopen from urllib.request import urlopen
from urllib.parse import urlencode from urllib.parse import urlencode
@ -15,10 +15,9 @@ import pypandoc
import markdown import markdown
class Config(object): class Config(object):
APPLICATION_ROOT = '/'
PORTNUMBER = int(os.environ.get('OCTOMODE_PORTNUMBER', 5001)) PORTNUMBER = int(os.environ.get('OCTOMODE_PORTNUMBER', 5001))
PAD_URL = os.environ.get('OCTOMODE_PAD_URL', 'https://pad.vvvvvvaria.org/' ) PAD_URL = os.environ.get('OCTOMODE_PAD_URL', 'https://pad.vvvvvvaria.org' )
PAD_API_URL = os.environ.get('OCTOMODE_PAD_API_URL', 'https://pad.vvvvvvaria.org/api/1.2.15/') PAD_API_URL = os.environ.get('OCTOMODE_PAD_API_URL', 'https://pad.vvvvvvaria.org/api/1.2.15')
PAD_API_KEY = os.environ.get('OCTOMODE_PAD_API_KEY', '') PAD_API_KEY = os.environ.get('OCTOMODE_PAD_API_KEY', '')
APP = Flask(__name__) APP = Flask(__name__)
@ -42,14 +41,14 @@ def get_pad_content(pad_name, ext=""):
'apikey' : APP.config['PAD_API_KEY'] 'apikey' : APP.config['PAD_API_KEY']
} }
api_call = 'getText' api_call = 'getText'
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode()))
# create pad in case it does not yet exist # create pad in case it does not yet exist
if response['code'] == 1 and 'padID does not exist' == response['message']: if response['code'] == 1 and 'padID does not exist' == response['message']:
api_call = 'createPad' api_call = 'createPad'
urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode()) urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode())
api_call = 'getText' api_call = 'getText'
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode()))
content = response['data']['text'] content = response['data']['text']
return content return content
@ -59,7 +58,7 @@ def all_pads():
'apikey' : APP.config['PAD_API_KEY'], 'apikey' : APP.config['PAD_API_KEY'],
} }
api_call = 'listAllPads' api_call = 'listAllPads'
response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode()))
return response return response
@ -83,7 +82,7 @@ def create_pad_on_first_run(name, ext):
'text' : default_template 'text' : default_template
} }
api_call = 'createPad' api_call = 'createPad'
json.load(urlopen(f"{ APP.config['PAD_API_URL'] }{ api_call }", data=urlencode(arguments).encode())) json.load(urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode()))
def md_to_html(md_pad_content): def md_to_html(md_pad_content):
# Convert Markdown to HTML # Convert Markdown to HTML
@ -120,35 +119,33 @@ def index():
exts = ['.md', '.css'] exts = ['.md', '.css']
for ext in exts: for ext in exts:
create_pad_on_first_run(name, ext) create_pad_on_first_run(name, ext)
return redirect(f'{ APP.config["APPLICATION_ROOT"] }{ name }/pad/') return redirect(f"/{ name }/pad")
else: else:
return render_template('start.html', application_root=APP.config["APPLICATION_ROOT"]) return render_template('start.html')
@APP.route('/<name>/') @APP.route('/<name>')
def main(name): def main(name):
return redirect(f'{ APP.config["APPLICATION_ROOT"] }{ name }/pad/') return redirect(f"/{ name }/pad")
@APP.route('/<name>/pad/') @APP.route('/<name>/pad')
def pad(name): def pad(name):
pad_name = f'{ name }.md' url = f"{ APP.config['PAD_URL'] }/{ name }.md"
url = os.path.join(APP.config['PAD_URL'], pad_name) return render_template('iframe.html', url=url, name=name.strip())
return render_template('iframe.html', url=url, name=name.strip(), application_root=APP.config["APPLICATION_ROOT"])
@APP.route('/<name>/stylesheet/') @APP.route('/<name>/stylesheet')
def stylesheet(name): def stylesheet(name):
pad_name = f'{ name }.css' url = f"{ APP.config['PAD_URL'] }/{ name }.css"
url = os.path.join(APP.config['PAD_URL'], pad_name) return render_template('iframe.html', url=url, name=name.strip())
return render_template('iframe.html', url=url, name=name.strip(), application_root=APP.config["APPLICATION_ROOT"])
@APP.route('/<name>/html/') @APP.route('/<name>/html')
def html(name): def html(name):
url = os.path.join(APP.config["APPLICATION_ROOT"], name, 'preview.html') url = f"/{ name }/preview.html"
return render_template('iframe.html', url=url, name=name.strip(), application_root=APP.config["APPLICATION_ROOT"]) return render_template('iframe.html', url=url, name=name.strip())
@APP.route('/<name>/pdf/') @APP.route('/<name>/pdf')
def pdf(name): def pdf(name):
url = os.path.join(APP.config["APPLICATION_ROOT"], name, 'pagedjs.html') url = f"/{name}/pagedjs.html"
return render_template('pdf.html', url=url, name=name.strip(), application_root=APP.config["APPLICATION_ROOT"]) return render_template('pdf.html', url=url, name=name.strip())
# ////////////////// # //////////////////
# RENDERED RESOURCES # RENDERED RESOURCES
@ -175,7 +172,7 @@ def preview(name):
lang = "en" lang = "en"
title = "No title" title = "No title"
return render_template('preview.html', name=name.strip(), pad_content=html, lang=lang, title=title, application_root=APP.config["APPLICATION_ROOT"]) return render_template('preview.html', name=name.strip(), pad_content=html, lang=lang, title=title)
@APP.route('/<name>/pagedjs.html') @APP.route('/<name>/pagedjs.html')
def pagedjs(name): def pagedjs(name):
@ -186,10 +183,10 @@ def pagedjs(name):
lang = metadata['language'][0] lang = metadata['language'][0]
title = metadata['title'][0] title = metadata['title'][0]
return render_template('pagedjs.html', name=name.strip(), pad_content=html, lang=lang, title=title, application_root=APP.config["APPLICATION_ROOT"]) return render_template('pagedjs.html', name=name.strip(), pad_content=html, lang=lang, title=title)
# ////////////////// # //////////////////
if __name__ == '__main__': if __name__ == '__main__':
APP.debug=True APP.debug=True
APP.run(host="0.0.0.0", port=f'{ APP.config["PORTNUMBER"] }', threaded=True) APP.run(host="0.0.0.0", port=APP.config["PORTNUMBER"], threaded=True)

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>{{ name }} in octomode</title> <title>{{ name }} in octomode</title>
<link rel="stylesheet" type="text/css" href="{{ application_root }}static/main.css"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
{% block head %} {% block head %}
{% endblock %} {% endblock %}
</head> </head>
@ -18,17 +18,21 @@ window.addEventListener('load', function () {
// Insert the nav buttons, after the page is loaded // Insert the nav buttons, after the page is loaded
const nav = document.createElement('div'); const nav = document.createElement('div');
nav.id = 'nav'; nav.id = 'nav';
const name = '{{ name }}';
const application_root = '{{ application_root }}';
nav.innerHTML = ` nav.innerHTML = `
<h1>${ name } <a href="${ application_root }"><em class="octomode">in octomode</em></a></h1> <h1>{{ name }} <a href="/"><em class="octomode">in octomode</em></a></h1>
<div id="buttons"> <div id="buttons">
<a href="${ application_root }${ name }/pad/"><button>pad</button></a>: <input type="text" name="pad" value="https://pad.vvvvvvaria.org/${ name }.md">
<a href="${ application_root }${ name }/stylesheet/"><button>stylesheet</button></a>: <input type="text" name="pad" value="https://pad.vvvvvvaria.org/${ name }.css"> <a href="/{{ name }}/pad"><button>pad</button></a>:
<a href="${ application_root }${ name }/html/"><button>html</button></a> <input type="text" name="pad" value="https://pad.vvvvvvaria.org/{{ name }}.md">
<a href="${ application_root }${ name }/pdf/"><button>pdf</button></a>
<a href="/{{ name }}/stylesheet"><button>stylesheet</button></a>:
<input type="text" name="pad" value="https://pad.vvvvvvaria.org/{{ name }}.css">
<a href="/{{ name }}/html"><button>html</button></a>
<a href="/{{ name }}/pdf"><button>pdf</button></a>
</div>`; </div>`;
document.body.insertBefore(nav, document.body.firstChild); document.body.insertBefore(nav, document.body.firstChild);

View File

@ -3,9 +3,9 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="{{ application_root }}static/paged.polyfill.js" type="text/javascript"></script> <script src="{{ url_for('static', filename='paged.polyfill.js') }}" type="text/javascript"></script>
<link href="{{ application_root }}static/pagedjs.css" rel="stylesheet" type="text/css" media="screen"> <link href="{{ url_for('static', filename='pagedjs.css') }}" rel="stylesheet" type="text/css" media="screen">
<link href="{{ application_root }}{{ name }}/stylesheet.css" rel="stylesheet" type="text/css" media="print"> <link href="/{{ name }}/stylesheet.css" rel="stylesheet" type="text/css" media="print">
<title>{{ title }}</title> <title>{{ title }}</title>
</head> </head>
<body> <body>

View File

@ -16,7 +16,7 @@ window.addEventListener('load', function () {
// Load the main.css again, to load the stylesheet for the nav // Load the main.css again, to load the stylesheet for the nav
var cssLink = document.createElement('link'); var cssLink = document.createElement('link');
cssLink.rel = 'stylesheet'; cssLink.rel = 'stylesheet';
cssLink.href = '{{ application_root }}/static/main.css'; cssLink.href = '{{ url_for("static", filename="main.css") }}';
var head = document.getElementsByTagName('head')[0]; var head = document.getElementsByTagName('head')[0];
head.insertBefore(cssLink, head.firstChild); head.insertBefore(cssLink, head.firstChild);

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{{ application_root }}/{{ name }}/stylesheet.css" rel="stylesheet" type="text/css" media="screen"> <link href="{{ name }}/stylesheet.css" rel="stylesheet" type="text/css" media="screen">
<title>{{ title }}</title> <title>{{ title }}</title>
</head> </head>
<body> <body>

View File

@ -3,10 +3,10 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>octomode</title> <title>octomode</title>
<link rel="stylesheet" type="text/css" href="{{ application_root }}static/main.css"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
</head> </head>
<body class="start-page"> <body class="start-page">
<form action="{{ application_root }}" method="POST"> <form action="/" method="POST">
<h1><input type="submit" value="open"> <input type="text" name="name"> <em class="octomode">in octomode</em></h1> <h1><input type="submit" value="open"> <input type="text" name="name"> <em class="octomode">in octomode</em></h1>
</form> </form>
</body> </body>