@@ -40,7 +40,7 @@ from datetime import datetime, timedelta
4040from time import time
4141from html import escape
4242from io import StringIO
43−from urllib.parse import urlencode, urljoin, urlparse
43+from urllib.parse import urlencode, urlparse
4444
4545from pygments import highlight
4646from pygments.lexers import get_lexer_by_name
@@ -269,14 +269,7 @@ def extract_domain(url):
269269
270270
271271def get_base_url():
272− if settings['server']['base_url']:
273− hostname = settings['server']['base_url']
274− else:
275− scheme = 'http'
276− if request.is_secure:
277− scheme = 'https'
278− hostname = url_for('index', _external=True, _scheme=scheme)
279− return hostname
272+ return url_for('index', _external=True)
280273
281274
282275def get_current_theme_name(override=None):
@@ -309,10 +302,6 @@ def url_for_theme(endpoint, override_theme=None, **values):
309302 if filename_with_theme in static_files:
310303 values['filename'] = filename_with_theme
311304 url = url_for(endpoint, **values)
312− if settings['server']['base_url']:
313− if url.startswith('/'):
314− url = url[1:]
315− url = urljoin(settings['server']['base_url'], url)
316305 return url
317306
318307
@@ -812,7 +801,7 @@ def preferences():
812801
813802 # save preferences
814803 if request.method == 'POST':
815− resp = make_response(redirect(urljoin(settings['server']['base_url'], url_for('index'))))
804+ resp = make_response(url_for('index', _external=True))
816805 try:
817806 request.preferences.parse_form(request.form)
818807 except ValidationException:
@@ -1002,11 +991,11 @@ def opensearch():
1002991 if request.headers.get('User-Agent', '').lower().find('webkit') >= 0:
1003992 method = 'get'
1004993
1005− ret = render('opensearch.xml',
1006− opensearch_method=method,
1007− host=get_base_url(),
1008− urljoin=urljoin,
1009− override_theme='__common__')
994+ ret = render(
995+ 'opensearch.xml',
996+ opensearch_method=method,
997+ override_theme='__common__'
998+ )
1010999
10111000 resp = Response(response=ret,
10121001 status=200,
@@ -1027,7 +1016,7 @@ def favicon():
10271016
10281017@app.route('/clear_cookies')
10291018def clear_cookies():
1030− resp = make_response(redirect(urljoin(settings['server']['base_url'], url_for('index'))))
1019+ resp = make_response(redirect(url_for('index', _external=True)))
10311020 for cookie_name in request.cookies:
10321021 resp.delete_cookie(cookie_name)
10331022 return resp
@@ -1128,19 +1117,38 @@ class ReverseProxyPathFix:
11281117 '''
11291118
11301119 def __init__(self, app):
1120+
11311121 self.app = app
1122+ self.script_name = None
1123+ self.scheme = None
1124+ self.server = None
1125+
1126+ if settings['server']['base_url']:
1127+
1128+ # If base_url is specified, then these values from are given
1129+ # preference over any Flask's generics.
1130+
1131+ base_url = urlparse(settings['server']['base_url'])
1132+ self.script_name = base_url.path
1133+ self.scheme = base_url.scheme
1134+ self.server = base_url.netloc
11321135
11331136 def __call__(self, environ, start_response):
1134− script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
1137+
1138+ script_name = self.script_name or environ.get('HTTP_X_SCRIPT_NAME', '')
11351139 if script_name:
11361140 environ['SCRIPT_NAME'] = script_name
11371141 path_info = environ['PATH_INFO']
11381142 if path_info.startswith(script_name):
11391143 environ['PATH_INFO'] = path_info[len(script_name):]
11401144
1141− scheme = environ.get('HTTP_X_SCHEME', '')
1145+ scheme = self.scheme or environ.get('HTTP_X_SCHEME', '')
11421146 if scheme:
11431147 environ['wsgi.url_scheme'] = scheme
1148+
1149+ server = self.server or environ.get('HTTP_X_FORWARDED_HOST', '')
1150+ if server:
1151+ environ['HTTP_HOST'] = server
11441152 return self.app(environ, start_response)
11451153
11461154