def check_methods(func, *args, **kwargs): """Wrapper for restrict""" if get_pylons(args).request.method not in methods: if get_pylons(args).request.params.get('_method') not in methods: log.debug("Method not allowed by restrict") abort(405, headers=[('Allow', ','.join(methods))]) return func(*args, **kwargs)
def dispatcher(func, self, *args, **kwargs): """Wrapper for dispatch_on""" alt_method = method_map.get(get_pylons(args).request.params.get('_method')) alt_method = method_map.get(get_pylons(args).request.method, alt_method) if alt_method: alt_method = getattr(self, alt_method) log.debug("Dispatching to %s instead", alt_method) return self._inspect_call(alt_method, **kwargs) return func(self, *args, **kwargs)
def dispatcher(func, self, *args, **kwargs): """Wrapper for dispatch_on""" alt_method = method_map.get(get_pylons(args).request.method) alt_method = method_map.get( get_pylons(args).request.params.get('_method'), alt_method) log.debug("Potentially dispatching to %s instead", alt_method) if alt_method: alt_method = getattr(self, alt_method) log.debug("Dispatching to %s instead", alt_method) return self._inspect_call(alt_method, **kwargs) return func(self, *args, **kwargs)
def api_response(func, *args, **kwargs): pylons = get_pylons(args) data = func(*args, **kwargs) format = pylons.request.params.get('format', 'json') if format == 'test': pylons.response.headers['Content-Type'] = 'text/plain' return pprint.pformat(data) elif format == 'xml': # a quick-dirty dict serializer def ser(d): r = "" for k,v in d.items(): if isinstance(v, dict): r += "<%s>%s</%s>" % (k, ser(v), k) elif isinstance(v, list): for i in v: #print k,i r += ser({k:i}) else: r += "<%s>%s</%s>" % (k, escape("%s"%v), k) return r pylons.response.headers['Content-Type'] = 'text/xml' return '<?xml version="1.0" encoding="UTF-8"?>' + ser({'response': data}).encode('utf-8') pylons.response.headers['Content-Type'] = 'application/json' res = json.dumps(data) #import sys;print >> sys.stderr, res return res
def wrapper(func, *args, **kwargs): """Decorator Wrapper function""" request = get_pylons(args).request if request.scheme.lower() == 'https': return func(*args, **kwargs) if request.method.upper() == 'POST': # don't allow POSTs (raises an exception) abort(405, headers=[('Allow', 'GET')]) if redirect_kwargs: # XXX: not a foolproof check for url_for arguments, but the # best we can do import warnings from routes import url_for warnings.warn( 'Calling https with url_for args is deprecated, use ' 'https(lambda: url(*args, **kwargs)) instead', DeprecationWarning, 2) redirect_kwargs['protocol'] = 'https' url = url_for(*redirect_args, **redirect_kwargs) elif not redirect_args: url = request.url else: url = redirect_args[0] if callable(url): url = url() # Ensure an https scheme, which also needs a host parts = urlparse.urlparse(url) url = urlparse.urlunparse(('https', parts[1] or request.host) + parts[2:]) log.debug('Redirecting non-https request: %s to: %s', request.path_info, url) redirect(url)
def wrapper(func, *args, **kwargs): """Decorator Wrapper function""" request = get_pylons(args).request if request.scheme.lower() == 'https': return func(*args, **kwargs) if request.method.upper() == 'POST': # don't allow POSTs (raises an exception) abort(405, headers=[('Allow', 'GET')]) if redirect_kwargs: # XXX: not a foolproof check for url_for arguments, but the # best we can do import warnings from routes import url_for warnings.warn('Calling https with url_for args is deprecated, use ' 'https(lambda: url(*args, **kwargs)) instead', DeprecationWarning, 2) redirect_kwargs['protocol'] = 'https' url = url_for(*redirect_args, **redirect_kwargs) elif not redirect_args: url = request.url else: url = redirect_args[0] if callable(url): url = url() # Ensure an https scheme, which also needs a host parts = urlparse.urlparse(url) url = urlparse.urlunparse(('https', parts[1] or request.host) + parts[2:]) log.debug('Redirecting non-https request: %s to: %s', request.path_info, url) redirect(url)
def jsonify(f, *args, **kwargs): """ Decorates methods in the controllers, and converts the output to a JSON serialization Args: f: The method to be called args: Parameters for f kwargs: Named parameters for f Returns: A string with the JSON representation of the value returned by f() """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' data = f(*args, **kwargs) if hasattr(data, '__iter__') and not isinstance(data, dict): return stream_response(data) else: log.debug('Sending directly json response') return [ json.dumps(data, cls=ClassEncoder, indent=None, sort_keys=False) ]
def cacheable(func, *args, **kwargs): pylons = get_pylons(args) del pylons.response.headers['Pragma'] del pylons.response.headers['Cache-Control'] pylons.response.cache_control = {'public': None} return func(*args, **kwargs)
def wrapper(func, *args, **kwargs): """Decorator wrapper""" pylons = get_pylons(args) log.debug("Wrapped with key: %s, expire: %s, type: %s, query_args: %s", key, expire, type, query_args) enabled = pylons.config.get("cache_enabled", "True") if not asbool(enabled): log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) if key: if query_args: key_dict = pylons.request.GET.mixed() else: key_dict = kwargs.copy() key_dict.update(_make_dict_from_args(func, args)) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: b_kwargs["type"] = type my_cache = pylons.cache.get_cache(namespace, **b_kwargs) if expire == "never": cache_expire = None else: cache_expire = expire def create_func(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) glob_response = pylons.response headers = glob_response.headerlist status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result) return full_response response = my_cache.get_value(cache_key, createfunc=create_func, expiretime=cache_expire, starttime=starttime) if cache_response: glob_response = pylons.response glob_response.headerlist = [header for header in response["headers"] if header[0].lower() in cache_headers] glob_response.status = response["status"] return response["content"]
def jsonify(f, *args, **kwargs): pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' try: data = f(*args, **kwargs) return json.dumps(data, cls = ClassEncoder, indent = 2, sort_keys = True) except HTTPException, e: jsonError = {'status': e.status, 'message': e.detail} resp = Response(json.dumps(jsonError), status = e.status, content_type='application/json') return resp(kwargs['environ'], kwargs['start_response'])
def jsonify(f, *args, **kwargs): pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' try: data = f(*args, **kwargs) return json.dumps(data, cls=ClassEncoder, indent=2, sort_keys=True) except HTTPException, e: jsonError = {'status': e.status, 'message': e.detail} resp = Response(json.dumps(jsonError), status=e.status, content_type='application/json') return resp(kwargs['environ'], kwargs['start_response'])
def jsonify(func, *args, **kwargs): pylons = get_pylons(args) pylons.response.headers["Content-Type"] = "application/json" data = func(*args, **kwargs) if isinstance(data, (list, tuple)): msg = ( "JSON responses with Array envelopes are susceptible to " "cross-site data leak attacks, see " "http://pylonshq.com/warnings/JSONArray" ) warnings.warn(msg, Warning, 2) log.warning(msg) log.debug("Returning JSON wrapped action output") return json.dumps(data, default=object_encoder)
def wrapper(func, *args, **kwargs): """Decorator Wrapper function""" request = get_pylons(args).request if request.scheme.lower() == 'https': return func(*args, **kwargs) else: if request.method.upper() != 'POST': redirect_kwargs['protocol'] = 'https' # ensure https log.debug('Redirecting non-https request: %s to redirect ' 'args: *%r, **%r', request.path_info, redirect_args, redirect_kwargs) redirect_to(*redirect_args, **redirect_kwargs) else: abort(405, headers=[('Allow', 'GET')]) # don't allow POSTs.
def kjsonify(func, *args, **kwargs): """Action decorator that formats output for JSON Given a function that will return content, this decorator will turn the result into JSON, with a content-type of 'application/json' and output it. CUSTOM: On exception, raise a KJsonifyException with keys: - in debug mode: type, exception, trace - in production: exception """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' try: data = func(*args, **kwargs) # Accept only dict objects for returned data. if not isinstance(data, (dict)): raise Exception( "kjsonify: bad data: only dictionaries are accepted.") warnings.warn(msg, Warning, 2) log.warning(msg) # Append global messages if any. if len(c.glob_messages): data['glob_msgs'] = map(lambda x: x.to_dict(), c.glob_messages) return simplejson.dumps(data) except Exception, e: exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() if config['debug']: # Log exception and debugging informations. log.debug("JSON exception:") for t in traceback.format_tb(exceptionTraceback): log.debug("%-9s: '%s'" % ("trace", str(t))) log.debug("%-9s: '%s'" % ("exception", str(e))) # Return ajax dictionary with exception details. raise KJsonifyException(str(exceptionType), str(exceptionValue), traceback.format_tb(exceptionTraceback)) else: # Log exception. log.debug("JSON exception: '%s'" % (str(e))) # Return generic error. raise KJsonifyException(str(exceptionType), 'Internal error')
def wrapper(func, *args, **kwargs): """Decorator Wrapper function""" request = get_pylons(args).request if request.scheme.lower() == 'https': return func(*args, **kwargs) else: if request.method.upper() != 'POST': redirect_kwargs['protocol'] = 'https' # ensure https log.debug( 'Redirecting non-https request: %s to redirect ' 'args: *%r, **%r', request.path_info, redirect_args, redirect_kwargs) redirect_to(*redirect_args, **redirect_kwargs) else: abort(405, headers=[('Allow', 'GET')]) # don't allow POSTs.
def kjsonify(func, *args, **kwargs): """Action decorator that formats output for JSON Given a function that will return content, this decorator will turn the result into JSON, with a content-type of 'application/json' and output it. CUSTOM: On exception, raise a KJsonifyException with keys: - in debug mode: type, exception, trace - in production: exception """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' try: data = func(*args, **kwargs) # Accept only dict objects for returned data. if not isinstance(data, (dict)): raise Exception("kjsonify: bad data: only dictionaries are accepted.") warnings.warn(msg, Warning, 2) log.warning(msg) # Append global messages if any. if len(c.glob_messages): data['glob_msgs'] = map(lambda x: x.to_dict(), c.glob_messages) return simplejson.dumps(data) except Exception, e: exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() if config['debug']: # Log exception and debugging informations. log.debug("JSON exception:") for t in traceback.format_tb(exceptionTraceback): log.debug("%-9s: '%s'" % ( "trace", str(t) ) ) log.debug("%-9s: '%s'" % ( "exception", str(e) ) ) # Return ajax dictionary with exception details. raise KJsonifyException(str(exceptionType), str(exceptionValue), traceback.format_tb(exceptionTraceback)) else: # Log exception. log.debug("JSON exception: '%s'" % ( str(e) ) ) # Return generic error. raise KJsonifyException(str(exceptionType), 'Internal error')
def ourjsonify(func, *args, **kwargs): """Action decorator that formats output for JSON Given a function that will return content, this decorator will turn the result into JSON, with a content-type of 'application/json' and output it. """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' data = func(*args, **kwargs) if isinstance(data, (list, tuple)): msg = "JSON responses with Array envelopes are susceptible to " \ "cross-site data leak attacks, see " \ "http://pylonshq.com/warnings/JSONArray" warnings.warn(msg, Warning, 2) log.warning(msg) return jsonpickle.encode(data, unpicklable=False)
def json_exception_response(func, *args, **kwargs): try: return func(*args, **kwargs) except HTTPException: raise except Exception, e: log.exception("%s(%s, %s) failed", func, args, kwargs) #pylons = get_pylons(args) #pylons.response.status_int = 500 metrics.track(get_pylons(args).request, 'unhandled-exception', function=func.__name__, error=e.__class__.__name__) return { 'result': None, 'error': { 'name': e.__class__.__name__, 'message': str(e) } }
def jsonify(f, *args, **kwargs): """ Decorates methods in the controllers, and converts the output to a JSON serialization Args: f: The method to be called args: Parameters for f kwargs: Named parameters for f Returns: A string with the JSON representation of the value returned by f() """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' data = f(*args, **kwargs) return [json.dumps(data, cls=ClassEncoder, indent=2, sort_keys=True)]
def jsonify(func, *args, **kwargs): """Action decorator that formats output for JSON Given a function that will return content, this decorator will turn the result into JSON, with a content-type of 'application/json' and output it. """ pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json; charset=utf-8' data = func(*args, **kwargs) if isinstance(data, (list, tuple)): msg = "JSON responses with Array envelopes are susceptible to " \ "cross-site data leak attacks, see " \ "http://wiki.pylonshq.com/display/pylonsfaq/Warnings" warnings.warn(msg, Warning, 2) log.warning(msg) log.debug("Returning JSON wrapped action output") return simplejson.dumps(data, cls=JSONEncoder, encoding='utf-8')
def wrapper(func, *args, **kwargs): result = func(*args, **kwargs) pylons = get_pylons(args) if not cache_enabled: log.debug("Caching disabled, skipping cache lookup") return result cfg_expires = "%s.expires" % _func_cname(func) cache_expires = expires if expires else int(pylons.config.get(cfg_expires, 0)) headers = pylons.response.headers status = pylons.response.status if pylons.response.status[0] not in ("4", "5"): if "Pragma" in headers: del headers["Pragma"] if "Cache-Control" in headers: del headers["Cache-Control"] headers["Last-Modified"] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime()) pylons.response.cache_expires(seconds=cache_expires) return result
def authenticate_form(func, *args, **kwargs): """Decorator for authenticating a form This decorator uses an authorization token stored in the client's session for prevention of certain Cross-site request forgery (CSRF) attacks (See http://en.wikipedia.org/wiki/Cross-site_request_forgery for more information). For use with the ``webhelpers.html.secure_form`` helper functions. """ request = get_pylons(args).request if authenticated_form(request.POST): del request.POST[secure_form.token_key] return func(*args, **kwargs) else: log.warn('Cross-site request forgery detected, request denied: %r ' 'REMOTE_ADDR: %s' % (request, request.remote_addr)) abort(403, detail=csrf_detected_message)
def wrapper(func, *args, **kwargs): result = func(*args, **kwargs) pylons = get_pylons(args) if not cache_enabled: log.debug("Caching disabled, skipping cache lookup") return result cfg_expires = "%s.expires" % _func_cname(func) cache_expires = expires if expires else int( pylons.config.get(cfg_expires, 0)) headers = pylons.response.headers status = pylons.response.status if pylons.response.status[0] not in ("4", "5"): if "Pragma" in headers: del headers["Pragma"] if "Cache-Control" in headers: del headers["Cache-Control"] headers["Last-Modified"] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime()) pylons.response.cache_expires(seconds=cache_expires) return result
def wrapper(func, *args, **kwargs): pylons = get_pylons(args) cb_name = pylons.request.params.get(cb) if cb_name is not None: pylons.response.headers['Content-Type'] = 'text/javascript' else: pylons.response.headers['Content-Type'] = 'application/json' data = func(*args, **kwargs) output = simplejson.dumps(data, **dumps_kwargs) if cb_name is not None: output = str(cb_name) + '(' + output + ');' log.debug("Returning JS wrapped action output") else: if isinstance(data, (list, tuple)): msg = "JSON responses with Array envelopes are susceptible to " \ "cross-site data leak attacks, see " \ "http://pylonshq.com/warnings/JSONArray" warnings.warn(msg, Warning, 2) log.warning(msg) log.debug("Returning JSON wrapped action output") return output
def wrapper(func, *args, **kwargs): """Decorator Wrapper function""" request = get_pylons(args).request if request.scheme.lower() == 'https': return func(*args, **kwargs) if request.method.upper() == 'POST': # don't allow POSTs (raises an exception) abort(405, headers=[('Allow', 'GET')]) if url_or_callable is None: url = request.url elif callable(url_or_callable): url = url_or_callable() else: url = url_or_callable # Ensure an https scheme, which also needs a host parts = urlparse.urlparse(url) url = urlparse.urlunparse(('https', parts[1] or request.host) + parts[2:]) log.debug('Redirecting non-https request: %s to: %s', request.path_info, url) redirect(url)
def wrapper(func, *args, **kwargs): """Decorator wrapper""" pylons = get_pylons(args) log.debug("Wrapped with key: %s, expire: %s, type: %s, query_args: %s", key, expire, type, query_args) enabled = pylons.config.get("cache_enabled", "True") if not asbool(enabled): log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) if key: if query_args: key_dict = pylons.request.GET.mixed() else: key_dict = kwargs.copy() key_dict.update(_make_dict_from_args(func, args)) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: b_kwargs['type'] = type my_cache = pylons.cache.get_cache(namespace, **b_kwargs) if expire == "never": cache_expire = None else: cache_expire = expire def create_func(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) glob_response = pylons.response headers = glob_response.headerlist status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result) return full_response response = my_cache.get_value(cache_key, createfunc=create_func, expiretime=cache_expire, starttime=starttime) if cache_response: glob_response = pylons.response glob_response.headerlist = [ header for header in response['headers'] if header[0].lower() in cache_headers ] glob_response.status = response['status'] return response['content']
def wrapper(func, *args, **kwargs): """Decorator wrapper""" pylons = get_pylons(args) log.debug("Wrapped with key: %s, expire: %s, type: %s, query_args: %s", key, expire, type, query_args) enabled = pylons.config.get("cache_enabled", "True") if not asbool(enabled): log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) if key: key_dict = kwargs.copy() key_dict.update(_make_dict_from_args(func, args)) ## FIXME: if we can stop there variables from being passed to the controller # action then we can use the stock beaker_cache. # Remove some system variables that can cause issues while generating cache keys [ key_dict.pop(x, None) for x in ("pylons", "start_response", "environ") ] if query_args: key_dict.update(pylons.request.GET.mixed()) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: b_kwargs['type'] = type cache_obj = getattr(pylons.app_globals, 'cache', None) if not cache_obj: cache_obj = getattr(pylons, 'cache', None) if not cache_obj: raise Exception('No cache object found') my_cache = cache_obj.get_cache(namespace, **b_kwargs) if expire == "never": cache_expire = None else: cache_expire = expire def create_func(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) glob_response = pylons.response headers = glob_response.headerlist status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result) return full_response response = my_cache.get_value(cache_key, createfunc=create_func, expiretime=cache_expire, starttime=starttime) if cache_response: glob_response = pylons.response glob_response.headerlist = [ header for header in response['headers'] if header[0].lower() in cache_headers ] glob_response.status = response['status'] return response['content']
def wrapper(func, *args, **kwargs): pylons = get_pylons(args) if not cache_enabled: log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) cfg_expires = "%s.expires" % _func_cname(func) # this section copies entirely too much from beaker cache if key: if query_args: key_dict = pylons.request.GET.mixed() else: key_dict = kwargs.copy() # beaker only does this if !query_args, we do it in # all cases to support both query args and method args # in the controller key_dict.update(_make_dict_from_args(func, args)) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: cache_kwargs["type"] = type my_cache = pylons.cache.get_cache(namespace, **cache_kwargs) ## end copy from beaker_cache last_modified = test(*args, **kwargs) cache_miss = list() def render(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) glob_response = pylons.response headers = dict(glob_response.headerlist) status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result, timestamp=last_modified) cache_miss.append(True) return full_response response = my_cache.get_value(cache_key, createfunc=render) timestamp = response["timestamp"] if timestamp < last_modified: my_cache.remove(cache_key) response = my_cache.get_value(cache_key, createfunc=render) glob_response = pylons.response if response["status"][0] in ("4", "5"): # do not cache 4XX, 5XX my_cache.remove(cache_key) else: headers = dict(glob_response.headerlist) headers.update(header for header in response["headers"].items() if header[0].lower() in cache_headers) headers["Last-Modified"] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(last_modified)) headers["ETag"] = str(last_modified) if cache_miss: headers["X-CKAN-Cache"] = "MISS" else: headers["X-CKAN-Cache"] = "HIT" if expires: if "Pragma" in headers: del headers["Pragma"] if "Cache-Control" in headers: del headers["Cache-Control"] else: headers["Pragma"] = "no-cache" headers["Cache-Control"] = "no-cache" glob_response.headerlist = headers.items() if expires: glob_response.cache_expires(seconds=expires) cc = glob_response.headers["Cache-Control"] glob_response.headers["Cache-Control"] = "%s, must-revalidate" % cc glob_response.status = response['status'] return response["content"]
def wrapper(func, *args, **kwargs): pylons = get_pylons(args) if not cache_enabled: log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) cfg_expires = "%s.expires" % _func_cname(func) # this section copies entirely too much from beaker cache if key: if query_args: key_dict = pylons.request.GET.mixed() else: key_dict = kwargs.copy() # beaker only does this if !query_args, we do it in # all cases to support both query args and method args # in the controller key_dict.update(_make_dict_from_args(func, args)) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: cache_kwargs["type"] = type my_cache = pylons.cache.get_cache(namespace, **cache_kwargs) ## end copy from beaker_cache last_modified = test(*args, **kwargs) cache_miss = list() def render(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) glob_response = pylons.response headers = dict(glob_response.headerlist) status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result, timestamp=last_modified) cache_miss.append(True) return full_response response = my_cache.get_value(cache_key, createfunc=render) timestamp = response["timestamp"] if timestamp < last_modified: my_cache.remove(cache_key) response = my_cache.get_value(cache_key, createfunc=render) glob_response = pylons.response if response["status"][0] in ("4", "5"): # do not cache 4XX, 5XX my_cache.remove(cache_key) else: headers = dict(glob_response.headerlist) headers.update(header for header in response["headers"].items() if header[0].lower() in cache_headers) headers["Last-Modified"] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(last_modified)) headers["ETag"] = str(last_modified) if cache_miss: headers["X-CKAN-Cache"] = "MISS" else: headers["X-CKAN-Cache"] = "HIT" if expires: if "Pragma" in headers: del headers["Pragma"] if "Cache-Control" in headers: del headers["Cache-Control"] else: headers["Pragma"] = "no-cache" headers["Cache-Control"] = "no-cache" glob_response.headerlist = headers.items() if expires: glob_response.cache_expires(seconds=expires) cc = glob_response.headers["Cache-Control"] glob_response.headers[ "Cache-Control"] = "%s, must-revalidate" % cc glob_response.status = response['status'] return response["content"]
def wrapper(func, *args, **kwargs): """Decorator wrapper""" pylons = get_pylons(args) log.debug("Wrapped with key: %s, expire: %s, type: %s, query_args: %s", key, expire, type, query_args) enabled = pylons.config.get("cache_enabled", "True") if not asbool(enabled): log.debug("Caching disabled, skipping cache lookup") return func(*args, **kwargs) if key: key_dict = kwargs.copy() key_dict.update(_make_dict_from_args(func, args)) ## FIXME: if we can stop there variables from being passed to the # controller action (also the Genshi Markup/pickle problem is # fixed, see below) then we can use the stock beaker_cache. # Remove some system variables that can cause issues while generating cache keys [key_dict.pop(x, None) for x in ("pylons", "start_response", "environ")] if query_args: key_dict.update(pylons.request.GET.mixed()) if key != "cache_default": if isinstance(key, list): key_dict = dict((k, key_dict[k]) for k in key) else: key_dict = {key: key_dict[key]} else: key_dict = None self = None if args: self = args[0] namespace, cache_key = create_cache_key(func, key_dict, self) if type: b_kwargs['type'] = type cache_obj = getattr(pylons.app_globals, 'cache', None) if not cache_obj: cache_obj = getattr(pylons, 'cache', None) if not cache_obj: raise Exception('No cache object found') my_cache = cache_obj.get_cache(namespace, **b_kwargs) if expire == "never": cache_expire = None else: cache_expire = expire def create_func(): log.debug("Creating new cache copy with key: %s, type: %s", cache_key, type) result = func(*args, **kwargs) # This is one of the two changes to the stock beaker_cache # decorator if hasattr(result, '__html__'): # Genshi Markup object, can not be pickled result = unicode(result.__html__()) glob_response = pylons.response headers = glob_response.headerlist status = glob_response.status full_response = dict(headers=headers, status=status, cookies=None, content=result) return full_response response = my_cache.get_value(cache_key, createfunc=create_func, expiretime=cache_expire, starttime=starttime) if cache_response: glob_response = pylons.response glob_response.headerlist = [header for header in response['headers'] if header[0].lower() in cache_headers] glob_response.status = response['status'] return response['content']
def _jsonpify(*args, **kwargs): pylons = get_pylons(args) pylons.response.headers['Content-Type'] = 'application/json' data = func(*args, **kwargs) log.debug("Returning JSONP wrapped action output") return prefix + '(' + simplejson.dumps(data) + ')'