예제 #1
0
def make_route(base_path, **kw):
    """ 
    Return a url path for a route
    make_route('/search/jobs', job_id=1234, action=delete)
    Can also add a query string by passing a list of tuples or a dict as _qs:
    make_route('/search/jobs', job_id=1234, action=delete, _qs=[('q', 'search val to quote')])
    or
    make_route('/search/jobs', job_id=1234, action=delete, _qs=dict(q='search val to quote'))
    """
    qargs = kw.get('_qs', '') 
    if qargs:
        del kw['_qs']
        if isinstance(qargs, dict):
            # translate {'v1':'k1', 'v2':['v2-1','v2-2']} to [('v1','k1'), ('v2','v2-1'), ('v2','v2-2')]
            # nexted list comprehensions ftw
            input = qargs; qargs = []
            [ qargs.extend([(k, e) for e in v]) for k,v in [ (k, v if isinstance(v, (list, tuple)) else (v,) ) for k, v in input.iteritems() ] ]
        qargs = '?'+'&'.join( [ '%s=%s' % (k,splunk.util.safeURLQuote(unicode(v))) for k,v in qargs ] ) 
    if not kw: 
        return i18n.make_i18n_url(base_path + qargs)

    app = cherrypy.request.app
    ctrl = app.root
    base_path = base_path.strip('/').split('/')
    for el in base_path:
        if hasattr(ctrl, el):
            newctrl = getattr(ctrl, el) 
            if not isinstance(newctrl, types.ObjectType):
                break
            ctrl = newctrl
        else:
            break
    # find route that matches kw
    for route in ctrl.routes:
        path = route.build_path(**kw)
        if path:
            base_path.extend(path)
            return i18n.make_i18n_url('/'+'/'.join([str(x) for x in base_path]) + qargs)
예제 #2
0
def make_url(target, _qs=None, translate=True, relative=False, __app_cache=None):
    """
    Build a url from a relative or absolute url with optional query string

    Set translate to false if you don't want /splunk (or whatever root_path in the config is set to)
    prefixed to the url - Usually you want this on though.
    Can also add a query string by passing a list of tuples or a dict as _qs:
    self.url('/search/jobs', job_id=1234, action=delete, _qs=[('q', 'search val to quote')])
    or
    self.url('/search/jobs', job_id=1234, action=delete, _qs=dict(q='search val to quote'))
    dict values can be strings or lists of strings 
    
    Static paths are constructed with a cache defeater segement embedded:
    
        /static/@<build_number>[.<push_number>]/
        
    This results in static paths like:
    
        /static/@12345/js/foo
        /static/@12345.1/js/foo
        
    Static assets for apps have an additional cache defeater number correlating to the app's
    build number as defined in app.conf:

        /static/@12345.1:2/app/unix/static/foo.png

    The URL handler in root.py strips out any requests with this schema
    """
    import i18n
    from splunk.appserver.mrsparkle.lib import module
    
    try:
        __app_cache = cherrypy.config['app_build_cache'] if __app_cache is None else __app_cache
    except KeyError:
        __app_cache = cherrypy.config['app_build_cache'] = {}

    if isinstance(target, list):
        target = '/'.join([safeURLQuote(x) for x in target])
        if not relative:
            target = '/' + target
    else:
        if not '?' in target:
            target = splunk.util.safeURLQuote(target)
            
    if not url_has_valid_charset(target):
        raise InvalidURLException("Illegal characters in URL")
        
    if _qs:
        if isinstance(_qs, dict):
            # translate {'v1':'k1', 'v2':['v2-1','v2-2']} to [('v1','k1'), ('v2','v2-1'), ('v2','v2-2')]
            # nexted list comprehensions ftw
            qargs = []
            [ qargs.extend([(k, e) for e in v]) for k,v in [ (k, v if isinstance(v, (list, tuple)) else (v,) ) for k, v in _qs.iteritems() ] ] 
            _qs = qargs
        qargs = '?' + '&'.join([ '%s=%s' % (safeURLQuote(unicode(k), safe=''), safeURLQuote(unicode(v), safe='')) for k, v in _qs])
    else:
        qargs = ''

    if translate and target[0]=='/':
        segments = target.split('/')
        target_segment = target.split('/', 2)[1] if target!='/' else ''

        if segments[1] in ('static', 'modules'):
            suffix = '.%s' % push_version() if push_version() else ''
            app_name = segments[3] if len(segments)>4 and segments[2]=='app' else None
            if segments[1] == 'modules' and len(segments) > 2:
                moduleList = module.moduleMapper.getInstalledModules()
                if moduleList.has_key('Splunk.Module.' + segments[2]):
                    app_name = moduleList.get('Splunk.Module.' + segments[2])['appName']

            if app_name:
                if app_name not in __app_cache:
                    # XXX Temporary hack to cache app config data until getConf() handles caching itself.
                    try:
                        rawConfig = splunk.bundle.getConf('app', namespace=app_name)
                        app_version = ':%d' % int(rawConfig['install'].get('build', 0))
                    except (splunk.ResourceNotFound, ValueError, TypeError):
                        app_version = ':0'
                    __app_cache[app_name] = app_version
                else:
                    app_version = __app_cache[app_name]
            else:
                app_version = ''

            target = target.replace('/%s/' % (target_segment,), '/%s/@%s%s%s/' % (target_segment, cherrypy.config['build_number'], suffix, app_version))
        return i18n.make_i18n_url(target+qargs)
    return target+qargs