Skip to content

Commit

Permalink
Set SERVER_NAME on Flask config
Browse files Browse the repository at this point in the history
Automatically set SERVER_NAME from the value of ckan.site_url. This is
needed so Flask is able to generate fully qualified URLs with
_external=True. One major thing to note is that when SERVER_NAME is set
up the incoming request `Host` header (`HTTP_HOST` in the WSGI environ)
must match its value, otherwise the Flask router will return a 404 even
if the route has been defined.

That's why we had to modify
1. The environ sent during the WSGI party invite requests
2. The environ sent with the test webtest app in tests
  • Loading branch information
amercader committed Jun 7, 2016
1 parent bf51545 commit 51805b2
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
16 changes: 12 additions & 4 deletions ckan/config/middleware/__init__.py
Expand Up @@ -97,8 +97,16 @@ def send_invitations(self, apps):
'''Call each app at the invite route to establish a partyline. Called
on init.'''
PATH = '/__invite__/'
# We need to send an environ tailored to `ckan.site_url`, otherwise
# Flask will return a 404 for the invite path (as we are using
# SERVER_NAME). Existance of `ckan.site_url` in config has already
# been checked.
parts = urlparse.urlparse(config.get('ckan.site_url'))
environ_overrides = {
'HTTP_HOST': parts.netloc,
}
for app_name, app in apps.items():
environ = create_environ(path=PATH)
environ = create_environ(PATH, environ_overrides=environ_overrides)
environ[self.partyline_key] = self.operator_class(self)
# A reference to the handling app. Used to id the app when
# responding to a handling request.
Expand Down Expand Up @@ -153,9 +161,9 @@ def __call__(self, environ, start_response):
return self.apps[app_name](environ, start_response)
else:
# Although this request will be served by Pylons we still
# need a request context (wich will create an app context) in order
# for the Flask URL builder to work
# need an application context in order for the Flask URL
# builder to work
flask_app = self.apps['flask_app']._flask_app

with flask_app.test_request_context(environ_overrides=environ):
with flask_app.app_context():
return self.apps[app_name](environ, start_response)
18 changes: 18 additions & 0 deletions ckan/config/middleware/flask_app.py
Expand Up @@ -2,6 +2,7 @@

import os
import itertools
import urlparse

from flask import Flask
from flask import abort as flask_abort
Expand Down Expand Up @@ -48,6 +49,23 @@ def make_flask_stack(conf, **app_conf):

# Do all the Flask-specific stuff before adding other middlewares

# Automatically set SERVER_NAME from the value of ckan.site_url. This is
# needed so Flask is able to generate fully qualified URLs with
# _external=True. One major thing to note is that when SERVER_NAME is set
# up the incoming request `Host` header (`HTTP_HOST` in the WSGI environ)
# must match its value, otherwise the Flask router will return a 404 even
# if the route has been defined.
if not app.config.get('SERVER_NAME'):
site_url = (os.environ.get('CKAN_SITE_URL') or
os.environ.get('CKAN__SITE_URL') or
app_conf.get('ckan.site_url'))
if not site_url:
raise RuntimeError(
'ckan.site_url is not configured and it must have a value.'
' Please amend your .ini file.')
parts = urlparse.urlparse(site_url)
app.config['SERVER_NAME'] = parts.netloc

# secret key needed for flask-debug-toolbar
app.config['SECRET_KEY'] = '<replace with a secret key>'
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
Expand Down
11 changes: 10 additions & 1 deletion ckan/tests/helpers.py
Expand Up @@ -19,6 +19,7 @@
This module is reserved for these very useful functions.
'''
import urlparse
import webtest
from pylons import config
import nose.tools
Expand Down Expand Up @@ -164,9 +165,17 @@ def _get_test_app():
Unit tests shouldn't need this.
'''

config['ckan.legacy_templates'] = False
app = ckan.config.middleware.make_app(config['global_conf'], **config)
app = CKANTestApp(app)

# As we are setting SERVER_NAME, Flask needs the HTTP_HOST header to match
# it otherwise the route mapper does not work (returns 404)
parts = urlparse.urlparse(config.get('ckan.site_url'))
extra_environ = {'HTTP_HOST': str(parts.netloc)}

app = CKANTestApp(app, extra_environ)

return app


Expand Down

0 comments on commit 51805b2

Please sign in to comment.