def wrapped(*args, **kwargs): # Identify if this is a GET or HEAD in order to proceed assert request.method in ['HEAD', 'GET'], '@etag is only supported for GET requests' rv = f(*args, **kwargs) rv = make_response(rv) # Some headers can change without data change for specific page content_headers = rv.headers.get('link', '') + rv.headers.get('count', '') + rv.headers.get('total-count', '') data = (rv.get_data().decode() + content_headers).encode() etag = generate_etag(data) rv.headers['Cache-Control'] = 'max-age=86400' rv.headers['ETag'] = etag if_match = request.headers.get('If-Match') if_none_match = request.headers.get('If-None-Match') if if_match: etag_list = [tag.strip() for tag in if_match.split(',')] if etag not in etag_list and '*' not in etag_list: raise PreconditionFailed('etag does not match') elif if_none_match: etag_list = [tag.strip() for tag in if_none_match.split(',')] if etag in etag_list or '*' in etag_list: raise NotModified return rv
def test_is_resource_modified_for_range_requests(self): env = create_environ() env['HTTP_IF_MODIFIED_SINCE'] = http.http_date( datetime(2008, 1, 1, 12, 30)) env['HTTP_IF_RANGE'] = http.generate_etag(b'awesome_if_range') # Range header not present, so If-Range should be ignored assert not http.is_resource_modified(env, data=b'not_the_same', ignore_if_range=False, last_modified=datetime( 2008, 1, 1, 12, 30)) env['HTTP_RANGE'] = '' assert not http.is_resource_modified( env, data=b'awesome_if_range', ignore_if_range=False) assert http.is_resource_modified(env, data=b'not_the_same', ignore_if_range=False) env['HTTP_IF_RANGE'] = http.http_date(datetime(2008, 1, 1, 13, 30)) assert http.is_resource_modified(env, last_modified=datetime( 2008, 1, 1, 14, 00), ignore_if_range=False) assert not http.is_resource_modified(env, last_modified=datetime( 2008, 1, 1, 13, 30), ignore_if_range=False) assert http.is_resource_modified(env, last_modified=datetime( 2008, 1, 1, 13, 30), ignore_if_range=True)
def wrapped(*args, **kwargs): # Identify if this is a GET or HEAD in order to proceed assert request.method in ['HEAD', 'GET' ], '@etag is only supported for GET requests' rv = method(*args, **kwargs) rv = make_response(rv) # Some headers can change without data change for specific page content_headers = (rv.headers.get('link', '') + rv.headers.get('count', '') + rv.headers.get('total-count', '')) data = (rv.get_data().decode() + content_headers).encode() etag = generate_etag(data) rv.headers['Cache-Control'] = 'max-age=%s' % cache_age rv.headers['ETag'] = etag if_match = request.headers.get('If-Match') if_none_match = request.headers.get('If-None-Match') if if_match: etag_list = [tag.strip() for tag in if_match.split(',')] if etag not in etag_list and '*' not in etag_list: raise PreconditionFailed('etag does not match') elif if_none_match: etag_list = [tag.strip() for tag in if_none_match.split(',')] if etag in etag_list or '*' in etag_list: raise NotModified return rv
def test_is_resource_modified_for_range_requests(self): env = create_environ() env["HTTP_IF_MODIFIED_SINCE"] = http.http_date(datetime(2008, 1, 1, 12, 30)) env["HTTP_IF_RANGE"] = http.generate_etag(b"awesome_if_range") # Range header not present, so If-Range should be ignored assert not http.is_resource_modified( env, data=b"not_the_same", ignore_if_range=False, last_modified=datetime(2008, 1, 1, 12, 30), ) env["HTTP_RANGE"] = "" assert not http.is_resource_modified( env, data=b"awesome_if_range", ignore_if_range=False ) assert http.is_resource_modified( env, data=b"not_the_same", ignore_if_range=False ) env["HTTP_IF_RANGE"] = http.http_date(datetime(2008, 1, 1, 13, 30)) assert http.is_resource_modified( env, last_modified=datetime(2008, 1, 1, 14, 00), ignore_if_range=False ) assert not http.is_resource_modified( env, last_modified=datetime(2008, 1, 1, 13, 30), ignore_if_range=False ) assert http.is_resource_modified( env, last_modified=datetime(2008, 1, 1, 13, 30), ignore_if_range=True )
def records(): form = forms.RecordFilterForm() # Cached data class_strings = get_cached_data("class_strings", 600, Record.get_classifications, with_regex=True) builds = get_cached_data("builds", 600, Record.get_builds) os_map = get_cached_data("os_map", 600, Record.get_os_map) # Form setup form.classification.choices = [(cs, cs) if "*" not in cs else (cs.replace("*", "%"), cs) for cs in class_strings] form.classification.choices.insert(0, ("All", "All")) form.build.choices = [(b[0], b[0]) for b in builds] form.build.choices.insert(0, ("All", "All")) form.severity.choices = [("All", "All"), ("1", "1 - low"), ("2", "2 - med"), ("3", "3 - high"), ("4", "4 - crit")] form.system_name.choices = [("All", "All")] + [(n, n) for n in os_map.keys()] form.machine_id.default = "" form.data_source.choices = [("All", "All")] + [('external', 'External'), ('internal', 'Internal')] if request.method == 'POST': return utils.records_post(form, request) elif request.method == 'GET': out_records = utils.records_get(form, request) return render_template('records.html', records=out_records, form=form, os_map=json.dumps(os_map)) elif request.method == 'HEAD': last_timestamp = Record.get_latest_timestamp_server() etag = werkzeug_http.generate_etag(int(last_timestamp).to_bytes(4, byteorder='big')) return Response(headers={'Etag': etag}) else: return Response('Invalid request method', status_code=404)
def add_etag(self, overwrite: bool = False, weak: bool = False) -> None: """Add an etag for the current response if there is none yet. .. versionchanged:: 2.0 SHA-1 is used to generate the value. MD5 may not be available in some environments. """ if overwrite or "etag" not in self.headers: self.set_etag(generate_etag(self.get_data()), weak)
def __call__(self, etag = None, data = None, include_weak = False): if [etag, data].count(None) != 1: raise TypeError('either tag or data required, but at least one') if etag is None: etag = generate_etag(data) if include_weak: if etag in self._weak: return True return etag in self._strong
def render_posts_atom(title, feed_id, posts): rv = make_response( render_template('posts.atom', title=title, feed_id=feed_id, posts=posts)) rv.headers['Content-Type'] = 'application/atom+xml; charset=utf-8' last_modified = max((p.updated for p in posts if p.updated), default=None) if last_modified: rv.headers['Last-Modified'] = http_date(last_modified) rv.headers['Etag'] = generate_etag(rv.get_data()) rv.make_conditional(request) return rv
def _compute_etag(cls, data): """ :param data: payload :return: """ if cap.config['AUTOCRUD_CONDITIONAL_REQUEST_ENABLED'] is True: if not isinstance(data, str): data = str(data if isinstance(data, (dict, list)) else data.to_dict(True)) return generate_etag(data.encode('utf-8')) return ""
def get(self, q=None, page=None): """Get styles.""" # Check cache to exit early if needed etag = generate_etag(current_ext.content_version.encode('utf8')) self.check_etag(etag, weak=True) # Build response res = jsonify(current_ext.styles) res.set_etag(etag) return res
def aggregated_etag(request): if request.url_rule is None: return if not hasattr(request, 'resource_adapters'): return resources = [a.resource \ for a in sorted(set(request.resource_adapters.values()), key=lambda a:a.resource.identifier)] return generate_etag(''.join(r.etag for r in resources).encode('ascii'))
def render_posts_atom(title, feed_id, posts): rv = make_response( render_template('posts.atom', title=title, feed_id=feed_id, posts=posts)) rv.headers['Content-Type'] = 'application/atom+xml; charset=utf-8' last_modified = max((p.updated for p in posts if p.updated), default=None) if last_modified: # rv.headers['Last-Modified'] = http_date(last_modified) rv.headers['Etag'] = generate_etag(rv.get_data()) rv.make_conditional(request) return rv
def test_etag_response_mixin_freezing(): class WithFreeze(wrappers.ETagResponseMixin, wrappers.BaseResponse): pass class WithoutFreeze(wrappers.BaseResponse, wrappers.ETagResponseMixin): pass response = WithFreeze("Hello World") response.freeze() strict_eq(response.get_etag(), (text_type(generate_etag(b"Hello World")), False)) response = WithoutFreeze("Hello World") response.freeze() assert response.get_etag() == (None, None) response = wrappers.Response("Hello World") response.freeze() assert response.get_etag() == (None, None)
def render_posts(title, posts, older, events=None, template='posts.jinja2'): atom_args = request.view_args.copy() atom_args.update({'feed': 'atom', '_external': True}) atom_url = url_for(request.endpoint, **atom_args) atom_title = title or 'Stream' rv = make_response( util.render_themed(template, posts=posts, title=title, older=older, atom_url=atom_url, atom_title=atom_title, events=events)) last_modified = max((p.updated for p in posts if p.updated), default=None) if last_modified: rv.headers['Last-Modified'] = http_date(last_modified) rv.headers['Etag'] = generate_etag(rv.get_data()) rv.make_conditional(request) return rv
def test_is_resource_modified(self): env = create_environ() # ignore POST env["REQUEST_METHOD"] = "POST" assert not http.is_resource_modified(env, etag="testing") env["REQUEST_METHOD"] = "GET" # etagify from data self.assert_raises(TypeError, http.is_resource_modified, env, data="42", etag="23") env["HTTP_IF_NONE_MATCH"] = http.generate_etag(b"awesome") assert not http.is_resource_modified(env, data=b"awesome") env["HTTP_IF_MODIFIED_SINCE"] = http.http_date(datetime(2008, 1, 1, 12, 30)) assert not http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 12, 00)) assert http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 13, 00))
def test_etag_response_mixin_freezing(): """Freeze of the etag response mixin adds etag if mixed first""" class WithFreeze(ETagResponseMixin, BaseResponse): pass class WithoutFreeze(BaseResponse, ETagResponseMixin): pass response = WithFreeze('Hello World') response.freeze() assert response.get_etag() == (generate_etag('Hello World'), False) response = WithoutFreeze('Hello World') response.freeze() assert response.get_etag() == (None, None) response = Response('Hello World') response.freeze() assert response.get_etag() == (None, None)
def wrapped(*args, **kwargs): # invoke the wrapped function and generate a response object from # its result rv = f(*args, **kwargs) response = make_response(rv) # etags only make sense for request that are cacheable, so only # GET and HEAD requests are processed if request.method not in ['GET', 'HEAD']: return response # if the response is not a code 200 OK then we let it through # unchanged if response.status_code != 200: return response # compute the etag for this request as the MD5 hash of the response # text and set it in the response header etag = generate_etag(response.get_data()) response.set_etag(etag) status = 200 # Handle If-Match and If-None-Match request headers if present if request.if_match: # Only return the response if the etag for this request matches # any of the etags given in the If-Match header. If there is no # match, then return a 412 Precondition Failed status code if etag not in request.if_match: status = 412 elif request.if_none_match: # Only return the response if the etag for this request does not # match any of the etags given in the If-None-Match header. If # one matches, then return a 304 Not Modified status code if etag in request.if_none_match: status = 304 # check if response needs to be modified due to ETags if status != 200: message = HTTP_STATUS_CODES[status] response = jsonify({ 'status': status, 'error': message, 'message': message }) response.status_code = status return response
def set_timestamp(self, resp: Response, model: Model) -> None: """ Set the ```Last-Modified`` to reflect the ``modified_at`` attribute of the model, if present. """ # pylint: disable=R0201 if hasattr(model, "modified_at"): resp.headers["Last-Modified"] = http.http_date(model.modified_at) # Setting an ETag, which identifies the ressource in time. if hasattr(model, "id"): raw = "{:#<10}{:0<10}{}".format( model.__class__.__name__, model.id, http.http_date(model.modified_at), ) resp.headers["ETag"] = http.generate_etag(raw.encode())
def test_is_resource_modified(self): env = create_environ() # ignore POST env['REQUEST_METHOD'] = 'POST' assert not http.is_resource_modified(env, etag='testing') env['REQUEST_METHOD'] = 'GET' # etagify from data pytest.raises(TypeError, http.is_resource_modified, env, data='42', etag='23') env['HTTP_IF_NONE_MATCH'] = http.generate_etag(b'awesome') assert not http.is_resource_modified(env, data=b'awesome') env['HTTP_IF_MODIFIED_SINCE'] = http.http_date(datetime(2008, 1, 1, 12, 30)) assert not http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 12, 00)) assert http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 13, 00))
def test_is_resource_modified(self): env = create_environ() # ignore POST env['REQUEST_METHOD'] = 'POST' assert not http.is_resource_modified(env, etag='testing') env['REQUEST_METHOD'] = 'GET' # etagify from data self.assert_raises(TypeError, http.is_resource_modified, env, data='42', etag='23') env['HTTP_IF_NONE_MATCH'] = http.generate_etag(b'awesome') assert not http.is_resource_modified(env, data=b'awesome') env['HTTP_IF_MODIFIED_SINCE'] = http.http_date(datetime(2008, 1, 1, 12, 30)) assert not http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 12, 00)) assert http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 13, 00))
def render_posts(title, posts, older, events=None, template='posts.jinja2'): atom_args = request.view_args.copy() atom_args.update({'feed': 'atom', '_external': True}) atom_url = url_for(request.endpoint, **atom_args) atom_title = title or 'Stream' rv = make_response( render_template(template, posts=posts, title=title, older=older, atom_url=atom_url, atom_title=atom_title, events=events)) last_modified = max((p.updated for p in posts if p.updated), default=None) if last_modified: # rv.headers['Last-Modified'] = http_date(last_modified) rv.headers['Etag'] = generate_etag(rv.get_data()) rv.make_conditional(request) return rv
def test_is_resource_modified(self): env = create_environ() # any method is allowed env["REQUEST_METHOD"] = "POST" assert http.is_resource_modified(env, etag="testing") env["REQUEST_METHOD"] = "GET" # etagify from data pytest.raises(TypeError, http.is_resource_modified, env, data="42", etag="23") env["HTTP_IF_NONE_MATCH"] = http.generate_etag(b"awesome") assert not http.is_resource_modified(env, data=b"awesome") env["HTTP_IF_MODIFIED_SINCE"] = http.http_date(datetime(2008, 1, 1, 12, 30)) assert not http.is_resource_modified( env, last_modified=datetime(2008, 1, 1, 12, 00) ) assert http.is_resource_modified( env, last_modified=datetime(2008, 1, 1, 13, 00) )
def render_post(post): if not post: abort(404) if post.deleted: abort(410) # deleted permanently if not check_audience(post): abort(401) if post.redirect: return redirect(post.redirect) rv = make_response( render_template('post.jinja2', post=post, title=post.title_or_fallback)) if post.updated: # rv.headers['Last-Modified'] = http_date(post.updated) rv.headers['Etag'] = generate_etag(rv.get_data()) rv.make_conditional(request) return rv
def render_post(post): if not post: abort(404) if post.deleted: abort(410) # deleted permanently if not check_audience(post): abort(401) # not authorized TODO a nicer page if post.redirect: return redirect(post.redirect) rv = make_response( util.render_themed('post.jinja2', post=post, title=post.title_or_fallback)) if post.updated: rv.headers['Last-Modified'] = http_date(post.updated) rv.headers['Etag'] = generate_etag(rv.get_data()) rv.make_conditional(request) return rv
def etag(self): return generate_etag(self.turtle_serialization)
def add_etag(self, overwrite = False, weak = False): if overwrite or 'etag' not in self.headers: self.set_etag(generate_etag(self.data), weak)
def test_etag_response_freezing(): response = Response("Hello World") response.freeze() assert response.get_etag() == (str(generate_etag(b"Hello World")), False)
def add_etag(self, overwrite=False, weak=False): """Add an etag for the current response if there is none yet.""" if overwrite or 'etag' not in self.headers: self.set_etag(generate_etag(self.data), weak)