diff options
author | Arun <engineerarun@gmail.com> | 2024-03-09 02:14:12 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-09 02:14:12 +0530 |
commit | 0e5bc21f7cebee60799ce1fa7d253e372c824ce5 (patch) | |
tree | 09355c1d4d18de91f01f5c1a02705a21da313ea0 | |
parent | f3a5cdf81e44fcf262a06dc7b774f939a71d0c70 (diff) | |
parent | 57ddd3e47ec081d80b2df127989c12647f2b6b1f (diff) |
Merge pull request #722 from LeXofLeviafan/fix-reverse-proxy
[jarun#685] included flask-reverse-proxy-fix into the package
-rw-r--r-- | bukuserver/middleware/__init__.py | 3 | ||||
-rw-r--r-- | bukuserver/middleware/flask_reverse_proxy_fix.py | 60 | ||||
-rw-r--r-- | bukuserver/requirements.txt | 1 | ||||
-rw-r--r-- | bukuserver/server.py | 9 | ||||
-rw-r--r-- | setup.py | 10 | ||||
-rw-r--r-- | tests/.pylintrc | 1 |
6 files changed, 68 insertions, 16 deletions
diff --git a/bukuserver/middleware/__init__.py b/bukuserver/middleware/__init__.py new file mode 100644 index 0000000..6a43d18 --- /dev/null +++ b/bukuserver/middleware/__init__.py @@ -0,0 +1,3 @@ +from .flask_reverse_proxy_fix import ReverseProxyPrefixFix + +__all__ = ['ReverseProxyPrefixFix'] diff --git a/bukuserver/middleware/flask_reverse_proxy_fix.py b/bukuserver/middleware/flask_reverse_proxy_fix.py new file mode 100644 index 0000000..4ac1f63 --- /dev/null +++ b/bukuserver/middleware/flask_reverse_proxy_fix.py @@ -0,0 +1,60 @@ +# clone of flask-reverse-proxy-fix with github fixes from @rachmadaniHaryono and @Glocktober + +from flask import Flask as App +# noinspection PyPackageRequirements +try: + from werkzeug.contrib.fixers import ProxyFix +except ModuleNotFoundError: + from werkzeug.middleware.proxy_fix import ProxyFix + + +class ReverseProxyPrefixFix: # pylint: disable=too-few-public-methods + """ + Flask middleware to ensure correct URLs are generated by Flask.url_for() where an application is under a reverse + proxy. Specifically this middleware corrects URLs where a common prefix needs to be added to all URLs. + + For example: If client requests for an application are reverse proxied such that: + `example.com/some-service/v1/foo` becomes `some-service-v1.internal/foo`, where `/foo` is a route within a Flask + application `foo()`. + + Without this middleware, a call to `Flask.url_for('.foo')` would give: `/foo`. If returned to the client, as a + 'self' link for example, this would cause a request to `example.com/foo`, which would be invalid as the + `/some-service/v1` prefix is missing. + + With this middleware, a call to `Flask.url_for('.foo')` would give: '/some-service/v1/foo', which will work if used + by a client. + + This middleware is compatible with both relative and absolute URLs (i.e. `Flask.url_for('.foo')` and + `Flask.url_for('.foo', _external=True)`. + + This middleware incorporates the `werkzeug.contrib.fixers.ProxyFix` middleware [1] and is based on the + 'Fixing SCRIPT_NAME/url_scheme when behind reverse proxy' Flask snippet [2]. + + Note: Ensure the prefix value includes a preceding slash, but not a trailing slash (i.e. use `/foo` not `/foo/`). + + [1] http://werkzeug.pocoo.org/docs/0.14/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix + [2] http://flask.pocoo.org/snippets/35/ + """ + def __init__(self, app: App, **kwargs): + """ + :type app: App + :param app: Flask application + """ + self.app = app.wsgi_app + self.prefix = None + + if 'REVERSE_PROXY_PATH' in app.config: + self.prefix = app.config['REVERSE_PROXY_PATH'] + + self.app = ProxyFix(self.app, **kwargs) + + app.wsgi_app = self + + def __call__(self, environ, start_response): + if self.prefix is not None: + environ['SCRIPT_NAME'] = self.prefix + path_info = environ['PATH_INFO'] + if path_info.startswith(self.prefix): + environ['PATH_INFO'] = path_info[len(self.prefix):] + + return self.app(environ, start_response) diff --git a/bukuserver/requirements.txt b/bukuserver/requirements.txt index cfc2a93..51b9325 100644 --- a/bukuserver/requirements.txt +++ b/bukuserver/requirements.txt @@ -3,7 +3,6 @@ Flask-Admin>=1.6.1 Flask-API>=3.0.post1 Flask-Bootstrap>=3.3.7.1 flask-paginate>=2022.1.8 -flask-reverse-proxy-fix @ https://github.com/rachmadaniHaryono/flask-reverse-proxy-fix/archive/refs/tags/v0.2.3.zip Flask-WTF>=1.0.1 Flask>=2.2.2,<2.3 werkzeug<2.4 diff --git a/bukuserver/server.py b/bukuserver/server.py index 7978a78..594f814 100644 --- a/bukuserver/server.py +++ b/bukuserver/server.py @@ -14,9 +14,9 @@ from flask_bootstrap import Bootstrap from buku import BukuDb, __version__, network_handler try: - from flask_reverse_proxy_fix.middleware import ReverseProxyPrefixFix + from .middleware import ReverseProxyPrefixFix except ImportError: - ReverseProxyPrefixFix = None + from bukuserver.middleware import ReverseProxyPrefixFix import click import flask from flask import __version__ as flask_version # type: ignore @@ -99,10 +99,7 @@ def create_app(db_file=None): if reverse_proxy_path.endswith('/'): print('Warning: reverse proxy path should not include trailing slash') app.config['REVERSE_PROXY_PATH'] = reverse_proxy_path - if ReverseProxyPrefixFix: - ReverseProxyPrefixFix(app) - else: - raise ImportError('Failed to import ReverseProxyPrefixFix') + ReverseProxyPrefixFix(app) bukudb = BukuDb(dbfile=app.config['BUKUSERVER_DB_FILE']) app.config['FLASK_ADMIN_SWATCH'] = (os.getenv('BUKUSERVER_THEME') or 'default').lower() app.config['BUKUSERVER_LOCALE'] = os.getenv('BUKUSERVER_LOCALE') or 'en' @@ -45,13 +45,6 @@ server_require = [ "Flask>=2.2.2,<2.3", "werkzeug<2.4", ] -reverse_proxy = " ".join( - [ - "flask-reverse-proxy-fix", - "@", - "https://github.com/rachmadaniHaryono/flask-reverse-proxy-fix/archive/refs/tags/v0.2.3.zip", - ] -) install_requires = [ 'beautifulsoup4>=4.4.1', 'certifi', @@ -82,9 +75,8 @@ setup( 'console_scripts': ['buku=buku:main', 'bukuserver=bukuserver.server:cli'] }, extras_require={ - "tests": tests_require + server_require + [reverse_proxy], + "tests": tests_require + server_require, "server": server_require, - "reverse_proxy": [reverse_proxy], "docs": [ "myst-parser>=0.17.0", "sphinx-rtd-theme>=1.0.0", diff --git a/tests/.pylintrc b/tests/.pylintrc index 327a12a..a401113 100644 --- a/tests/.pylintrc +++ b/tests/.pylintrc @@ -2,6 +2,7 @@ disable= assigning-non-slot, broad-except, + c-extension-no-member, consider-using-f-string, consider-using-with, dangerous-default-value, |