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)
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