From c844d02f1c7558e959891de75494cffd22dc323f Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 25 Aug 2011 12:13:55 +0100 Subject: [PATCH] Added the APPLICATION_ROOT configuration variable which is used by session backends. --- CHANGES | 1 + docs/config.rst | 10 +++++++++- flask/app.py | 1 + flask/sessions.py | 12 ++++++++++-- tests/flask_tests.py | 22 ++++++++++++++++++++++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index dc288966..6ba980aa 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,7 @@ Relase date to be decided, codename to be chosen. conceptionally only instance depending and outside version control so it's the perfect place to put configuration files etc. For more information see :ref:`instance-folders`. +- Added the ``APPLICATION_ROOT`` configuration variable. Version 0.7.3 ------------- diff --git a/docs/config.rst b/docs/config.rst index 57bea926..eb9d0e06 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -77,6 +77,13 @@ The following configuration values are used internally by Flask: ``SERVER_NAME`` the name and port number of the server. Required for subdomain support (e.g.: ``'localhost:5000'``) +``APPLICATION_ROOT`` If the application does not occupy + a whole domain or subdomain this can + be set to the path where the application + is configured to live. This is for + session cookie as path value. If + domains are used, this should be + ``None``. ``MAX_CONTENT_LENGTH`` If set to a value in bytes, Flask will reject incoming requests with a content length greater than this by @@ -134,7 +141,8 @@ The following configuration values are used internally by Flask: ``PROPAGATE_EXCEPTIONS``, ``PRESERVE_CONTEXT_ON_EXCEPTION`` .. versionadded:: 0.8 - ``TRAP_BAD_REQUEST_ERRORS``, ``TRAP_HTTP_EXCEPTIONS`` + ``TRAP_BAD_REQUEST_ERRORS``, ``TRAP_HTTP_EXCEPTIONS``, + ``APPLICATION_ROOT`` Configuring from Files ---------------------- diff --git a/flask/app.py b/flask/app.py index 35577984..6ad69975 100644 --- a/flask/app.py +++ b/flask/app.py @@ -236,6 +236,7 @@ class Flask(_PackageBoundObject): 'USE_X_SENDFILE': False, 'LOGGER_NAME': None, 'SERVER_NAME': None, + 'APPLICATION_ROOT': None, 'MAX_CONTENT_LENGTH': None, 'TRAP_BAD_REQUEST_ERRORS': False, 'TRAP_HTTP_EXCEPTIONS': False diff --git a/flask/sessions.py b/flask/sessions.py index ee006cda..fda84a25 100644 --- a/flask/sessions.py +++ b/flask/sessions.py @@ -127,6 +127,13 @@ class SessionInterface(object): # chop of the port which is usually not supported by browsers return '.' + app.config['SERVER_NAME'].rsplit(':', 1)[0] + def get_cookie_path(self, app): + """Returns the path for which the cookie should be valid. The + default implementation uses the value from the ``APPLICATION_ROOT`` + configuration variable or uses ``/`` if it's `None`. + """ + return app.config['APPLICATION_ROOT'] or '/' + def get_expiration_time(self, app, session): """A helper method that returns an expiration date for the session or `None` if the session is linked to the browser session. The @@ -169,9 +176,10 @@ class SecureCookieSessionInterface(SessionInterface): def save_session(self, app, session, response): expires = self.get_expiration_time(app, session) domain = self.get_cookie_domain(app) + path = self.get_cookie_path(app) if session.modified and not session: - response.delete_cookie(app.session_cookie_name, + response.delete_cookie(app.session_cookie_name, path=path, domain=domain) else: - session.save_cookie(response, app.session_cookie_name, + session.save_cookie(response, app.session_cookie_name, path=path, expires=expires, httponly=True, domain=domain) diff --git a/tests/flask_tests.py b/tests/flask_tests.py index 220bf4cb..db8275d6 100644 --- a/tests/flask_tests.py +++ b/tests/flask_tests.py @@ -339,6 +339,28 @@ class BasicFunctionalityTestCase(unittest.TestCase): assert 'domain=.example.com' in rv.headers['set-cookie'].lower() assert 'httponly' in rv.headers['set-cookie'].lower() + def test_session_using_application_root(self): + class PrefixPathMiddleware(object): + def __init__(self, app, prefix): + self.app = app + self.prefix = prefix + def __call__(self, environ, start_response): + environ['SCRIPT_NAME'] = self.prefix + return self.app(environ, start_response) + + app = flask.Flask(__name__) + app.wsgi_app = PrefixPathMiddleware(app.wsgi_app, '/bar') + app.config.update( + SECRET_KEY='foo', + APPLICATION_ROOT='/bar' + ) + @app.route('/') + def index(): + flask.session['testing'] = 42 + return 'Hello World' + rv = app.test_client().get('/', 'http://example.com:8080/') + assert 'path=/bar' in rv.headers['set-cookie'].lower() + def test_missing_session(self): app = flask.Flask(__name__) def expect_exception(f, *args, **kwargs):