~cedric/newspipe

1

[PATCH] improved support for reverse-proxy and virtual path

Details
Message ID
<CABSMGamXhBxjER1gCu6CZ+9OVViBw76uLk-Bm-OV5P7K1x6tcA@mail.gmail.com>
DKIM signature
missing
Download raw message
From: "B. Stack" <bgstack15@gmail.com>

    This adds the python logic, and prefix variable to assembled
    links in html and js
---
 instance/config.py                 |  3 +++
 instance/sqlite.py                 |  3 +++
 newspipe/bootstrap.py              | 19 +++++++++++++++++++
 newspipe/controllers/user.py       |  2 +-
 newspipe/static/js/articles.js     |  6 +++---
 newspipe/static/js/config.js       |  7 +++++++
 newspipe/templates/article.html    |  2 +-
 newspipe/templates/duplicates.html |  6 +++---
 newspipe/templates/history.html    |  2 +-
 newspipe/templates/home.html       | 10 +++++-----
 newspipe/templates/layout.html     |  3 ++-
 newspipe/templates/login.html      |  2 +-
 newspipe/templates/management.html |  2 +-
 13 files changed, 50 insertions(+), 17 deletions(-)
 create mode 100644 newspipe/static/js/config.js

diff --git a/instance/config.py b/instance/config.py
index 42e624c..af7617a 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 1f8d620..c6eaa46 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 1204491..1c5c967 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 00ffb96..d2c5bc0 100644
--- a/newspipe/controllers/user.py
+++ b/newspipe/controllers/user.py
@@ -138,7 +138,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/js/articles.js b/newspipe/static/js/articles.js
index f1cee6e..29ebac2 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 0000000..7fad438
--- /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/article.html b/newspipe/templates/article.html
index c62e3f0..d9cf9a6 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 38dc52b..d138226 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>&nbsp;<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>&nbsp;<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>&nbsp;<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>&nbsp;<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 153c2f1..00e22ef 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 631b769..5feb18d 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 2464040..466ff4e 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 b995230..78af3c4 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 4e977f8..19dbded 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>
-- 
1.8.3.1
Details
Message ID
<20230916204925.Horde.QW1zw1d9-ejWah_UIp3vOnd@cloud.cedricbonhomme.org>
In-Reply-To
<CABSMGamXhBxjER1gCu6CZ+9OVViBw76uLk-Bm-OV5P7K1x6tcA@mail.gmail.com> (view parent)
DKIM signature
missing
Download raw message
Hello,
 
I had finally the time to check and apply your patch. I'll make some more tests but it's arelady pushed.
 
Again, thank you very much for your contribution !
 
 
With kind regards,
 
Cédric
Reply to thread Export thread (mbox)