Changeset 5690

Show
Ignore:
Timestamp:
11/17/08 06:36:45 (2 months ago)
Author:
carndt
Message:

Adding new 'absolute_url' function to 'controllers' module. Fixes #316

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1.1/CHANGELOG.txt

    r5689 r5690  
    2626* New config option ``safempfilter.on`` to enable the ``SafeMultipartFilter`` 
    2727  (see end of ``app.cfg`` in a quickstarted project for usage example) (r5666). 
    28  
     28* New function 'absolute_url', which wraps 'url' and returns a full absolute 
     29  URL, including scheme and host name (r5690) 
    2930 
    3031Changes 
  • branches/1.1/turbogears/controllers.py

    r5667 r5690  
    558558    return tgpath 
    559559 
     560def get_server_name(): 
     561    """Return name of the server this application runs on. 
     562 
     563    Respects 'Host' and 'X-Forwarded-Host' header. 
     564 
     565    See the docstring of the 'absolute_url' function for more information. 
     566 
     567    """ 
     568    get = config.get 
     569    h = request.headers 
     570    host = get('tg.url_domain') or h.get('X-Forwarded-Host', h.get('Host')) 
     571    if not host: 
     572        host = '%s:%s' % (get('server.socket_host', 'localhost'), 
     573            get('server.socket_port', 8080)) 
     574    return host 
     575 
     576def absolute_url(tgpath='/', params=None, **kw): 
     577    """Return absolute URL (including schema and host to this server). 
     578 
     579    Tries to account for 'Host' header and reverse proxying 
     580    ('X-Forwarded-Host'). 
     581 
     582    The host name is determined this way: 
     583 
     584    * If the config setting 'tg.url_domain' is set and non-null, use this value. 
     585    * Else, if the 'base_url_filter.use_x_forwarded_host' config setting is 
     586      True, use the value from the 'Host' or 'X-Forwarded-Host' request header. 
     587    * Else, if config setting 'base_url_filter.on' is True and 
     588      'base_url_filter.base_url' is non-null, use its value for the host AND 
     589      scheme part of the URL. 
     590    * As a last fallback, use the value of 'server.socket_host' and 
     591      'server.socket_port' config settings (defaults to 'localhost:8080'). 
     592 
     593    The URL scheme ('http' or 'http') used is determined in the following way: 
     594 
     595    * If 'base_url_filter.base_url' is used, use the scheme from this URL. 
     596    * If there is a 'X-Use-SSL' request header, use 'https'. 
     597    * Else, if the config setting 'tg.url_scheme' is set, use its value. 
     598    * Else, use the value of 'cherrypy.request.scheme'. 
     599 
     600    """ 
     601    get = config.get 
     602    use_xfh = get('base_url_filter.use_x_forwarded_host', False) 
     603    if request.headers.get('X-Use-SSL'): 
     604        scheme = 'https' 
     605    else: 
     606        scheme = get('tg.url_scheme') 
     607    if not scheme: 
     608        scheme = request.scheme 
     609    base_url = '%s://%s' % (scheme, get_server_name()) 
     610    if get('base_url_filter.on', False) and not use_xfh: 
     611        base_url = get('base_url_filter.base_url').rstrip('/') 
     612    return '%s%s' % (base_url, url(tgpath, params, **kw)) 
    560613 
    561614def check_app_root(): 
     
    610663__all__ = [ 
    611664    "Controller", 
     665    "absolute_url", 
    612666    "error_handler", 
    613667    "exception_handler", 
    614668    "expose", 
     669    "get_server_name", 
    615670    "flash", 
    616671    "redirect", 
  • branches/1.1/turbogears/__init__.py

    r3241 r5690  
    44 
    55from turbogears import config 
    6 from turbogears.controllers import expose, flash, validate, redirect, \ 
    7                                    error_handler, exception_handler, url 
    8 from turbogears import controllers, view, database, validators, command, \ 
    9                        i18n, widgets, startup, scheduler 
    10 from turbogears.release import version as __version__, author as __author__, \ 
    11                                email as __email__, license as __license__, \ 
    12                                copyright as __copyright__ 
     6from turbogears.controllers import (absolute_url, expose, flash, validate, 
     7    redirect, error_handler, exception_handler, url) 
     8from turbogears import (controllers, view, database, validators, command, 
     9    i18n, widgets, startup, scheduler) 
     10from turbogears.release import (version as __version__, author as __author__, 
     11    email as __email__, license as __license__, copyright as __copyright__) 
    1312from turbogears.widgets import mochikit 
    1413from turbogears.widgets import jsi18nwidget 
     
    2726 
    2827 
    29 __all__ = ["url", "expose", "redirect", "validate", "flash", 
    30            "error_handler", "exception_handler", 
    31            "view", "controllers", "update_config", 
    32            "database", "command", "validators", "mochikit", "widgets", 
    33            "config", "start_server", "scheduler"] 
     28__all__ = [ 
     29    "absolute_url", 
     30    "database", 
     31    "command", 
     32    "config", 
     33    "controllers", 
     34    "expose", 
     35    "flash", 
     36    "error_handler", 
     37    "exception_handler", 
     38    "mochikit", 
     39    "redirect", 
     40    "scheduler", 
     41    "start_server", 
     42    "update_config", 
     43    "url", 
     44    "validate", 
     45    "validators", 
     46    "view", 
     47    "widgets", 
     48
  • branches/1.1/turbogears/tests/test_controllers.py

    r5514 r5690  
    44import cherrypy 
    55import pkg_resources 
    6 from turbogears import config, controllers, database, \ 
    7     error_handler, exception_handler, expose, flash, redirect, \ 
    8     startup, testutil, url, validate, validators, util 
     6from turbogears import (absolute_url, config, controllers, database, 
     7    error_handler, exception_handler, expose, flash, redirect, startup, 
     8    testutil, url, util, validate, validators) 
    99 
    1010 
     
    264264        return 
    265265 
     266    @expose() 
     267    def absolute_url(self, url='/'): 
     268        return absolute_url(url) 
    266269 
    267270class TestRoot(testutil.TGTest): 
     
    723726        assert 'foo' in url('/foo', params, spamm='ham') 
    724727        assert params['spamm'] == 'eggs' 
     728 
     729class TestAbsoluteURLs(testutil.TGTest): 
     730    root = MyRoot 
     731 
     732    #def setUp(self): 
     733    #    super(TestAbsoluteURLs, self).setUp() 
     734    # 
     735    #def tearDown(self): 
     736    #    super(TestAbsoluteURLs, self).tearDown() 
     737    #    config.update({"server.webpath": ""}) 
     738 
     739    def _config_update(self, data=None, **kw): 
     740        self.config_backup = {} 
     741        if not data: 
     742            data = {} 
     743        else: 
     744            data = data.copy() 
     745        data.update(kw) 
     746        for k in data: 
     747            self.config_backup[k] = config.get(k) 
     748        config.update(data) 
     749 
     750    def _config_reset(self): 
     751        config.update(self.config_backup) 
     752 
     753    def test_scheme_from_config(self): 
     754        """absolute_url() gets correct URL scheme from 'tg.url_scheme' setting 
     755        """ 
     756        hostname = 'foo.org' 
     757        scheme = 'https' 
     758        self._config_update({ 
     759            "base_url_filter.on": False, 
     760            "base_url_filter.use_x_forwarded_host": True, 
     761            "tg.url_scheme": scheme 
     762        }) 
     763        url = self.app.get('/absolute_url/?url=%2Ffoo', 
     764            headers={'X-Forwarded-Host': hostname}).body 
     765        self._config_reset() 
     766        print url 
     767        assert url == '%s://%s/foo' % (scheme, hostname) 
     768 
     769    def test_scheme_from_header(self): 
     770        """absolute_url() gets correct URL scheme from 'X-Use-SSL' header""" 
     771        hostname = 'foo.org' 
     772        scheme = 'https' 
     773        self._config_update({ 
     774            "base_url_filter.on": False, 
     775            "base_url_filter.use_x_forwarded_host": True, 
     776        }) 
     777        url = self.app.get('/absolute_url/?url=%2Ffoo', 
     778            headers={'X-Forwarded-Host': hostname, 'X-Use-SSL': scheme}).body 
     779        self._config_reset() 
     780        print url 
     781        assert url == '%s://%s/foo' % (scheme, hostname) 
     782 
     783    def test_use_base_url(self): 
     784        """absolute_url() gets correct host name from 'base_url' setting""" 
     785        hostname = 'foo.org' 
     786        port = 1234 
     787        self._config_update({ 
     788            "base_url_filter.on": True, 
     789            "base_url_filter.use_x_forwarded_host": False, 
     790            "base_url_filter.base_url": 'http://%s:%s' % (hostname, port) 
     791        }) 
     792        url = self.app.get('/absolute_url/?url=%2Ffoo').body 
     793        self._config_reset() 
     794        print url 
     795        assert url == 'http://%s:%s/foo' % (hostname, port) 
     796 
     797    def test_use_config(self): 
     798        """absolute_url() gets correct host name from 'tg.url_domain' setting""" 
     799        hostname = 'foo.org' 
     800        port = 1234 
     801        self._config_update({ 
     802            "base_url_filter.on": False, 
     803            "base_url_filter.use_x_forwarded_host": False, 
     804            "tg.url_domain": '%s:%s' % (hostname, port) 
     805        }) 
     806        url = self.app.get('/absolute_url/?url=%2Ffoo').body 
     807        self._config_reset() 
     808        print url 
     809        assert url == 'http://%s:%s/foo' % (hostname, port) 
     810 
     811    def test_use_host(self): 
     812        """absolute_url() gets correct host name from 'Host' header""" 
     813        self._config_update({ 
     814            "base_url_filter.on": False, 
     815            "base_url_filter.use_x_forwarded_host": False, 
     816        }) 
     817        hostname = 'foo.org' 
     818        url = self.app.get('/absolute_url/?url=%2Ffoo', 
     819            headers={'Host': hostname}).body 
     820        self._config_reset() 
     821        print url 
     822        assert url == 'http://%s/foo' % hostname 
     823 
     824    def test_use_server_config(self): 
     825        """absolute_url() gets correct host name from server config""" 
     826        hostname = 'foo.org' 
     827        port = 1234 
     828        self._config_update({ 
     829            "base_url_filter.on": False, 
     830            "base_url_filter.use_x_forwarded_host": False, 
     831            'server.socket_host': hostname, 
     832            'server.socket_port': port 
     833        }) 
     834        url = self.app.get('/absolute_url/?url=%2Ffoo', 
     835            headers={'Host': ''}).body 
     836        self._config_reset() 
     837        print url 
     838        assert url == 'http://%s:%s/foo' % (hostname, port) 
     839 
     840    def test_use_x_forwarded_host(self): 
     841        """absolute_url() gets correct host name from 'X-Forwarded-Host' header""" 
     842        self._config_update({ 
     843            "base_url_filter.on": False, 
     844            "base_url_filter.use_x_forwarded_host": True, 
     845        }) 
     846        hostname = 'foo.org' 
     847        url = self.app.get('/absolute_url/?url=%2Ffoo', 
     848            headers={'X-Forwarded-Host': hostname}).body 
     849        self._config_reset() 
     850        print url 
     851        assert url == 'http://%s/foo' % hostname