diff options
-rw-r--r-- | instance/config.py | 3 | ||||
-rw-r--r-- | instance/sqlite.py | 3 | ||||
-rw-r--r-- | newspipe/bootstrap.py | 19 | ||||
-rw-r--r-- | newspipe/controllers/user.py | 8 | ||||
-rw-r--r-- | newspipe/static/css/custom.css | 72 | ||||
-rw-r--r-- | newspipe/static/js/articles.js | 6 | ||||
-rw-r--r-- | newspipe/static/js/config.js | 7 | ||||
-rw-r--r-- | newspipe/templates/about.html | 1 | ||||
-rw-r--r-- | newspipe/templates/about_more.html | 2 | ||||
-rw-r--r-- | newspipe/templates/article.html | 2 | ||||
-rw-r--r-- | newspipe/templates/duplicates.html | 6 | ||||
-rw-r--r-- | newspipe/templates/history.html | 2 | ||||
-rw-r--r-- | newspipe/templates/home.html | 10 | ||||
-rw-r--r-- | newspipe/templates/layout.html | 3 | ||||
-rw-r--r-- | newspipe/templates/login.html | 2 | ||||
-rw-r--r-- | newspipe/templates/management.html | 2 | ||||
-rw-r--r-- | newspipe/web/__init__.py | 11 | ||||
-rw-r--r-- | newspipe/web/views/user.py | 1 | ||||
-rw-r--r-- | newspipe/web/views/views.py | 4 |
19 files changed, 127 insertions, 37 deletions
diff --git a/instance/config.py b/instance/config.py index 42e624cb..af7617a4 100644 --- a/instance/config.py +++ b/instance/config.py @@ -10,6 +10,9 @@ PORT = 5000 DEBUG = True API_ROOT = "/api/v2.0" +# Optional, and useful if you are using a reverse proxy with this virtual path prefix +#PREFIX = "/newspipe" + CSRF_ENABLED = True SECRET_KEY = "LCx3BchmHRxFzkEv4BqQJyeXRLXenf" SECURITY_PASSWORD_SALT = "L8gTsyrpRQEF8jNWQPyvRfv7U5kJkD" diff --git a/instance/sqlite.py b/instance/sqlite.py index 1f8d6206..c6eaa461 100644 --- a/instance/sqlite.py +++ b/instance/sqlite.py @@ -10,6 +10,9 @@ PORT = 5000 DEBUG = True API_ROOT = "/api/v2.0" +# Optional, and useful if you are using a reverse proxy with this virtual path prefix +#PREFIX = "/newspipe" + CSRF_ENABLED = True SECRET_KEY = "LCx3BchmHRxFzkEv4BqQJyeXRLXenf" SECURITY_PASSWORD_SALT = "L8gTsyrpRQEF8jNWQPyvRfv7U5kJkD" diff --git a/newspipe/bootstrap.py b/newspipe/bootstrap.py index 12044916..1c5c967d 100644 --- a/newspipe/bootstrap.py +++ b/newspipe/bootstrap.py @@ -44,6 +44,14 @@ def set_logging( handler.setLevel(log_level) logger.setLevel(log_level) +class ReverseProxied(object): + def __init__(self, app, script_name): + self.app = app + self.script_name = script_name + + def __call__(self, environ, start_response): + environ['SCRIPT_NAME'] = self.script_name + return self.app(environ, start_response) # Create Flask application application = Flask(__name__, instance_relative_config=True) @@ -63,6 +71,11 @@ else: set_logging(application.config["LOG_PATH"]) +_prefix = "" +if "PREFIX" in application.config: + application.wsgi_app = ReverseProxied(application.wsgi_app, script_name=application.config["PREFIX"]) + _prefix = application.config["PREFIX"] + db = SQLAlchemy(application) migrate = Migrate(application, db) @@ -100,3 +113,9 @@ application.jinja_env.filters["datetime"] = format_datetime application.jinja_env.filters["datetimeformat"] = datetimeformat # inject application in Jinja env application.jinja_env.globals["application"] = application + +@application.context_processor +def utility_processor(): + def prefix(): + return _prefix.rstrip("/") + return dict(prefix=prefix) diff --git a/newspipe/controllers/user.py b/newspipe/controllers/user.py index 00ffb96a..54137794 100644 --- a/newspipe/controllers/user.py +++ b/newspipe/controllers/user.py @@ -5,6 +5,7 @@ import ldap3 from ldap3.core.exceptions import LDAPBindError from werkzeug.security import check_password_hash from werkzeug.security import generate_password_hash +from urllib.parse import urlparse from .abstract import AbstractController from newspipe.bootstrap import application @@ -17,6 +18,11 @@ from newspipe.models import User logger = logging.getLogger(__name__) +# FOR LDAP +# Reference: session_app +import ldap3 +from ldap3.core.exceptions import LDAPBindError, LDAPPasswordIsMandatoryError + class UserController(AbstractController): _db_cls = User @@ -138,7 +144,7 @@ class LdapuserController: namelist = [] try: query = dns.resolver.query(f"_ldap._tcp.{domain}", "SRV") - except dns.resolver.NXDOMAIN: + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): # no records exist that match the request, so we were probably # given a specific hostname, and an empty query will trigger # the logic below that will add the original domain to the list. diff --git a/newspipe/static/css/custom.css b/newspipe/static/css/custom.css index 70a24bf8..65625f0e 100644 --- a/newspipe/static/css/custom.css +++ b/newspipe/static/css/custom.css @@ -1,3 +1,13 @@ +:root { + /* primary color, for header bar, links, etc. */ + --main-color: #bc0900; + /* right side of header bar, border around some buttons, button hover color */ + --main-shade: #7f0600; + /* color of active button */ + --main-tint: #ed0b00; + /* very light color, not used at present, but designed for the background of (2n+1) table rows */ + --main-accent: #fcf5f4; +} html { position: relative; min-height: 100%; @@ -11,8 +21,9 @@ body { img { padding: 2px; } -a { - color: #3572B0; +a, a.nav-link { + /*color: #3572B0;*/ + color: var(--main-color); } #sidebar { @@ -33,28 +44,55 @@ a { rgb(255, 255, 255, 1); } +a:hover,a.nav-link:hover { + color: var(--main-shade); +} + .bg-newspipe-blue { /* background-color: #0082c9; */ - background-image: linear-gradient(40deg, #0082c9 0%, #30b6ff 100%); + /* background-image: linear-gradient(40deg, #0082c9 0%, #30b6ff 100%); */ + background-image: linear-gradient(40deg, var(--main-color) 0%, var(--main-shade) 100%); } .btn-primary { - background-color: #0082c9; + /* background-color: #0082c9; */ + background-color: var(--main-color); + border-color: var(--main-shade); opacity: 1; color: white; } .btn-secondary { - background-color: #0082c9; + /* background-color: #0082c9; */ + background-color: var(--main-color); opacity: 0.6; color: white; } +.btn-primary:hover, .btn-secondary { + background-color: var(--main-shade); +} .btn-outline-primary { - border-color: #0082c9; - color: #0082c9; + /* border-color: #0082c9; + color: #0082c9; */ + border-color: var(--main-color); + color: var(--main-color); +} + +.btn-primary:hover { + border-color: var(--main-shade); +} + +.btn-primary:active, .btn.btn-primary:active, .btn-secondary:active, a.btn.btn-primary:active { + background-color: var(--main-tint); + border: var(--main-tint); +} + +.dropdown-item:active, a.dropdown-item:active { + background-color: var(--main-tint); } .bg-primary { - background-color: #0082c9 !important; + /* background-color: #0082c9 !important; */ + background-color: var(--main-color) !important; opacity: 1; color: white; text-align: center; @@ -63,7 +101,12 @@ a { .badge-light { background-color: rgb(246, 248, 250); opacity: 1; - color: #0082c9 !important; + /* color: #0082c9 !important; */ + color: var(--main-color) !important; +} + +.badge:hover { + color: var(--main-shade); } /* Main table for the list of news */ @@ -113,3 +156,14 @@ a { .pagination-page-info { display: inline; } + +.fa-square-o::before, .fa-checked-square-o::before, .fa-star-o::before { + color: var(--main-color); +} + +/* + * Unnecessary +.table-striped tbody tr:nth-of-type(2n+1) { + background-color: var(--main-accent); +} + */ diff --git a/newspipe/static/js/articles.js b/newspipe/static/js/articles.js index f1cee6e7..29ebac2e 100644 --- a/newspipe/static/js/articles.js +++ b/newspipe/static/js/articles.js @@ -86,7 +86,7 @@ Array.prototype.map.call(nodes, function(node) { } // sends the updates to the server - fetch(API_ROOT + "article/" + article_id, { + fetch(prefix + API_ROOT + "article/" + article_id, { method: "PUT", headers: { 'Content-Type': 'application/json', @@ -157,7 +157,7 @@ Array.prototype.map.call(nodes, function(node) { } // sends the updates to the server - fetch(API_ROOT + "article/" + article_id, { + fetch(prefix + API_ROOT + "article/" + article_id, { method: "PUT", headers: { 'Content-Type': 'application/json', @@ -189,7 +189,7 @@ Array.prototype.map.call(nodes, function(node) { data = JSON.stringify(data); // sends the updates to the server - fetch(API_ROOT + "articles", { + fetch(prefix + API_ROOT + "articles", { method: "DELETE", headers: { 'Content-Type': 'application/json', diff --git a/newspipe/static/js/config.js b/newspipe/static/js/config.js new file mode 100644 index 00000000..7fad4388 --- /dev/null +++ b/newspipe/static/js/config.js @@ -0,0 +1,7 @@ +/* + * Set variables here for the javascript used by newspipe. + */ +var prefix = "/newspipe"; + +/* Set exactly one trailing slash on prefix. */ +prefix = prefix.replace(/\/+$/,"/"); diff --git a/newspipe/templates/about.html b/newspipe/templates/about.html index 45703ea0..973c086e 100644 --- a/newspipe/templates/about.html +++ b/newspipe/templates/about.html @@ -12,6 +12,7 @@ <p>{{ _('Found a bug? Report it <a href="https://todo.sr.ht/~cedric/newspipe">here</a>.') }} {{ _('A documentation is available <a href="https://man.sr.ht/~cedric/newspipe">here</a>.') }}</p> <p><a href="{{ url_for('about_more') }}">{{ _('More information') }}</a> {{ _('about this instance.') }}</p> + <p><a href="{{ git_url }}">This fork's source</a></p> </div> </div> <br /> diff --git a/newspipe/templates/about_more.html b/newspipe/templates/about_more.html index 0df05852..6f01681f 100644 --- a/newspipe/templates/about_more.html +++ b/newspipe/templates/about_more.html @@ -5,7 +5,7 @@ <div class="col"> <h2>{{ _('Information about this instance') }}</h2> <ul class="list-group"> - <li class="list-group-item">{{ _('Newspipe version') }}: <em><a href="{{ version_url }}">{{newspipe_version}}</a></em></li> + <li class="list-group-item">{{ _('Newspipe version') }}: <em>{{newspipe_version}}</em></li> <li class="list-group-item">{{ _('Python version') }}: <em>{{python_version}}</em></li> <li class="list-group-item">{{ _('Registration') }}: <em>{{registration}}</em></li> <li class="list-group-item">{{ _('Number of users') }}: <em>{{nb_users}}</em></li> diff --git a/newspipe/templates/article.html b/newspipe/templates/article.html index c62e3f0c..d9cf9a62 100644 --- a/newspipe/templates/article.html +++ b/newspipe/templates/article.html @@ -4,7 +4,7 @@ <div class="row" data-article="{{ article.id }}" id="filters" data-filter="{{ filter_ }}"> <div class="col"> <h2><a href="{{ article.link }}" target="_blank">{{ article.title|safe }}</a></h2> - <h3>{{ _('from') }} <a href="/feed/{{ article.source.id }}">{{ article.source.title }}</a></h3> + <h3>{{ _('from') }} <a href="{{ prefix() }}/feed/{{ article.source.id }}">{{ article.source.title }}</a></h3> <a href="{{ url_for("article.delete", article_id=article.id) }}"><i class="fa fa-times delete" aria-hidden="true" title="{{ _('Delete this article') }}"></i></a> {% if article.like %} <a href="#"><i class="fa fa-star like" aria-hidden="true" title="{{ _('One of your favorites') }}"></i></a> diff --git a/newspipe/templates/duplicates.html b/newspipe/templates/duplicates.html index 38dc52b1..d1382268 100644 --- a/newspipe/templates/duplicates.html +++ b/newspipe/templates/duplicates.html @@ -1,7 +1,7 @@ {% extends "layout.html" %} {% block content %} <div class="container"> - <p><h1>{{ _('Duplicates in the feed') }} <a href="/feed/{{ feed.id }}">{{ feed.title }}</a>.</h1><p> + <p><h1>{{ _('Duplicates in the feed') }} <a href="{{ prefix() }}/feed/{{ feed.id }}">{{ feed.title }}</a>.</h1><p> <div class="table-responsive"> <table class="table table-striped"> <thead> @@ -19,8 +19,8 @@ {% for pair in duplicates %} <tr> <td>{{ loop.index }}</td> - <td id="{{ pair[0].id }}"><a href="{{ url_for("article.delete", article_id=pair[0].id) }}"><i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"></i></a> <a href="/article/{{ pair[0].id }}">{{ pair[0].title }}</a> ({{ pair[0].retrieved_date }})</td> - <td id="{{ pair[1].id }}"><a href="{{ url_for("article.delete", article_id=pair[1].id) }}"><i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"></i></a> <a href="/article/{{ pair[1].id }}">{{ pair[1].title }}</a> ({{ pair[1].retrieved_date }})</td> + <td id="{{ pair[0].id }}"><a href="{{ url_for("article.delete", article_id=pair[0].id) }}"><i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"></i></a> <a href="{{ prefix() }}/article/{{ pair[0].id }}">{{ pair[0].title }}</a> ({{ pair[0].retrieved_date }})</td> + <td id="{{ pair[1].id }}"><a href="{{ url_for("article.delete", article_id=pair[1].id) }}"><i class="fa fa-times" aria-hidden="true" title="{{ _('Delete this article') }}"></i></a> <a href="{{ prefix() }}/article/{{ pair[1].id }}">{{ pair[1].title }}</a> ({{ pair[1].retrieved_date }})</td> </tr> {% endfor %} </tbody> diff --git a/newspipe/templates/history.html b/newspipe/templates/history.html index 153c2f11..00e22ef3 100644 --- a/newspipe/templates/history.html +++ b/newspipe/templates/history.html @@ -43,7 +43,7 @@ <ul class="list-group"> {% for date in articles_counter | sort(reverse = True) %} {% for article in articles %} - <li class="list-group-item">{{ article.date | datetime }} - <a href="/article/{{ article.id }}">{{ article.title | safe }}</a></li> + <li class="list-group-item">{{ article.date | datetime }} - <a href="{{ prefix() }}/article/{{ article.id }}">{{ article.title | safe }}</a></li> {% endfor %} {% endfor %} </ul> diff --git a/newspipe/templates/home.html b/newspipe/templates/home.html index 631b769c..5feb18d1 100644 --- a/newspipe/templates/home.html +++ b/newspipe/templates/home.html @@ -42,7 +42,7 @@ {% if feed_id == feed.id %}</b>{% endif %} </a></li> <li class="nav-item feed-commands {% if in_error.get(fid, 0) > 0 %}d-none{% endif %}" data-bs-feed="{{ feed.id }}"><span class="nav-link"> - <a href="/feed/{{ feed.id }}"><i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"></i></a> + <a href="{{ prefix() }}/feed/{{ feed.id }}"><i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"></i></a> <a href="{{ url_for('feed.form', feed_id=feed.id) }}"><i class="fa fa-pencil-square-o" aria-hidden="true" title="{{ _('Edit this feed') }}"></i></a> <a href="{{ url_for('article.mark_as', new_value='unread', feed_id=feed.id) }}"><i class="fa fa-square-o" aria-hidden="true" title="{{ _('Mark this feed as unread') }}"></i></a> <a href="{{ url_for('article.mark_as', new_value='read', feed_id=feed.id) }}"><i class="fa fa-check-square-o" aria-hidden="true" title="{{ _('Mark this feed as read') }}"></i></a> @@ -73,7 +73,7 @@ {% if feed_id == fid %}</b>{% endif %} </a></li> <li class="nav-item feed-commands {% if in_error.get(fid, 0) > 0 %}d-none{% endif %}" data-bs-feed="{{ fid }}"><span class="nav-link"> - <a href="/feed/{{ fid }}"><i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"></i></a> + <a href="{{ prefix() }}/feed/{{ fid }}"><i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"></i></a> <a href="{{ url_for('feed.form', feed_id=fid) }}"><i class="fa fa-pencil-square-o" aria-hidden="true" title="{{ _('Edit this feed') }}"></i></a> <a href="{{ url_for('article.mark_as', new_value='unread', feed_id=fid) }}"><i class="fa fa-square-o" aria-hidden="true" title="{{ _('Mark this feed as unread') }}"></i></a> <a href="{{ url_for('article.mark_as', new_value='read', feed_id=fid) }}"><i class="fa fa-check-square-o" aria-hidden="true" title="{{ _('Mark this feed as read') }}"></i></a> @@ -102,7 +102,7 @@ {% if feed_id == fid %}</b>{% endif %} </a></li> <li class="nav-item feed-commands {% if in_error.get(fid, 0) > 0 %}d-none{% endif %}" data-bs-feed="{{ fid }}"><span class="nav-link"> - <a href="/feed/{{ fid }}"><i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"></i></a> + <a href="{{ prefix() }}/feed/{{ fid }}"><i class="fa fa-info" aria-hidden="true" title="{{ _('Details') }}"></i></a> <a href="{{ url_for('feed.form', feed_id=fid) }}"><i class="fa fa-pencil-square-o" aria-hidden="true" title="{{ _('Edit this feed') }}"></i></a> <a href="{{ url_for('article.mark_as', new_value='unread', feed_id=fid) }}"><i class="fa fa-square-o" aria-hidden="true" title="{{ _('Mark this feed as unread') }}"></i></a> <a href="{{ url_for('article.mark_as', new_value='read', feed_id=fid) }}"><i class="fa fa-check-square-o" aria-hidden="true" title="{{ _('Mark this feed as read') }}"></i></a> @@ -174,11 +174,11 @@ {% if not feed_id %} <td class="d-none d-md-block"> <img src="{{ url_for('icon.icon', url=feeds[article.source.id].icon_url) }}" width="16px"> - <a href="/article/redirect/{{ article.id}}" target="_blank">{{ article.source.title | safe }}</a> + <a href="{{ prefix() }}/article/redirect/{{ article.id}}" target="_blank">{{ article.source.title | safe }}</a> </td> {% endif %} <td {%if filter_ == 'all' and article.readed == False %}style='font-weight:bold'{% endif %}> - <a href="/article/{{ article.id }}" title="{{ article.title }}">{{ article.title | truncate(100, False, '...') }}</a> + <a href="{{ prefix() }}/article/{{ article.id }}" title="{{ article.title }}">{{ article.title | truncate(100, False, '...') }}</a> </td> <td class="date d-none d-lg-block">{{ article.date | datetime(format='short') }}</td> </tr> diff --git a/newspipe/templates/layout.html b/newspipe/templates/layout.html index 2464040c..466ff4e2 100644 --- a/newspipe/templates/layout.html +++ b/newspipe/templates/layout.html @@ -21,7 +21,7 @@ {% block menu %} <nav class="navbar navbar-expand-lg navbar-dark bg-newspipe-blue"> <div class="container-fluid"> - <a class="navbar-brand" href="/">Newspipe</a> + <a class="navbar-brand" href="{{ prefix() }}/">Newspipe</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> @@ -150,6 +150,7 @@ {% block content %}{% endblock %} <!-- Placed at the end of the document so the pages load faster --> + <script type="text/javascript" src="{{ url_for('static', filename = 'js/config.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename = 'js/articles.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename = 'js/feed.js') }}"></script> </body> diff --git a/newspipe/templates/login.html b/newspipe/templates/login.html index b9952309..78af3c4a 100644 --- a/newspipe/templates/login.html +++ b/newspipe/templates/login.html @@ -19,7 +19,7 @@ <div class="alert alert-warning" role="alert">{{ message }}</div> {% endfor %} {{ form.submit(class_="btn btn-primary") }} - {% if self_registration %}<a href="/signup" class="btn btn-info">{{ _('Sign up') }}</a>{% endif %} + {% if self_registration %}<a href="{{ prefix() }}/signup" class="btn btn-info">{{ _('Sign up') }}</a>{% endif %} </form> </div> </div> diff --git a/newspipe/templates/management.html b/newspipe/templates/management.html index 4e977f84..19dbded0 100644 --- a/newspipe/templates/management.html +++ b/newspipe/templates/management.html @@ -6,7 +6,7 @@ <div class="row"> <div class="col"> <h2>{{ _('Your subscriptions') }}</h2> - <p>{{ _('You are subscribed to') }} {{ nb_feeds }} <a href="/feeds">{{ _('feeds') }}</a>. <a href="{{ url_for("feed.form") }}">{{ _('Add') }}</a> {{ _('a feed') }}.</p> + <p>{{ _('You are subscribed to') }} {{ nb_feeds }} <a href="{{ prefix() }}/feeds">{{ _('feeds') }}</a>. <a href="{{ url_for("feed.form") }}">{{ _('Add') }}</a> {{ _('a feed') }}.</p> <p>{{ nb_articles }} {{ _('articles are stored in the database with') }} {{ nb_unread_articles }} {{ _('unread articles') }}.</p> <p>{{ _('You have') }} {{ nb_categories }} <a href="{{ url_for("categories.list_")}}">{{ _('categories') }}</a>.</p> <a href="{{ url_for("articles.expire", weeks=10) }}" class="btn btn-primary" onclick="return confirm('{{ _('You are going to delete old articles.') }}');">{{ _('Delete articles older than 10 weeks') }}</a> diff --git a/newspipe/web/__init__.py b/newspipe/web/__init__.py index 9cd78b88..cbda2235 100644 --- a/newspipe/web/__init__.py +++ b/newspipe/web/__init__.py @@ -10,11 +10,6 @@ import subprocess BASE_DIR = os.path.abspath(os.path.dirname(__file__)) -__version__ = ( - os.environ.get("PKGVER") - or subprocess.run( - ["git", "-C", BASE_DIR, "describe", "--tags"], stdout=subprocess.PIPE - ) - .stdout.decode() - .strip() -) +# bgstack15 +__version__ = "v9.5.1" +__git_url__ = "https://bgstack15.ddns.net/cgit/newspipe" diff --git a/newspipe/web/views/user.py b/newspipe/web/views/user.py index 5f2240bc..6550403c 100644 --- a/newspipe/web/views/user.py +++ b/newspipe/web/views/user.py @@ -9,6 +9,7 @@ from flask_login import current_user from flask_login import login_required from flask_paginate import get_page_args from flask_paginate import Pagination +from werkzeug.exceptions import BadRequest from newspipe.bootstrap import application from newspipe.controllers import ArticleController diff --git a/newspipe/web/views/views.py b/newspipe/web/views/views.py index 3fc446e0..92724bb6 100644 --- a/newspipe/web/views/views.py +++ b/newspipe/web/views/views.py @@ -17,7 +17,7 @@ from newspipe.bootstrap import application from newspipe.bootstrap import talisman from newspipe.controllers import FeedController from newspipe.controllers import UserController -from newspipe.web import __version__ +from newspipe.web import __version__, __git_url__ from newspipe.web.lib.view_utils import etag_match logger = logging.getLogger(__name__) @@ -88,7 +88,7 @@ def popular(): @current_app.route("/about", methods=["GET"]) @etag_match def about(): - return render_template("about.html", contact=application.config["ADMIN_EMAIL"]) + return render_template("about.html", contact=application.config["ADMIN_EMAIL"], git_url=__git_url__) @current_app.route("/about/more", methods=["GET"]) |