def validate_since(): """Validate the current Last-Modified against If-Modified-Since headers. If no code has set the Last-Modified response header, then no validation will be performed. """ response = cherrypy.response lastmod = response.headers.get('Last-Modified') if lastmod: status, reason, msg = _http.valid_status(response.status) request = cherrypy.request since = request.headers.get('If-Unmodified-Since') if since and since != lastmod: if (status >= 200 and status <= 299) or status == 412: raise cherrypy.HTTPError(412) since = request.headers.get('If-Modified-Since') if since and since == lastmod: if (status >= 200 and status <= 299) or status == 304: if request.method in ("GET", "HEAD"): raise cherrypy.HTTPRedirect([], 304) else: raise cherrypy.HTTPError(412)
def validate_etags(autotags=False): """Validate the current ETag against If-Match, If-None-Match headers. If autotags is True, an ETag response-header value will be provided from an MD5 hash of the response body (unless some other code has already provided an ETag header). If False (the default), the ETag will not be automatic. WARNING: the autotags feature is not designed for URL's which allow methods other than GET. For example, if a POST to the same URL returns no content, the automatic ETag will be incorrect, breaking a fundamental use for entity tags in a possibly destructive fashion. Likewise, if you raise 304 Not Modified, the response body will be empty, the ETag hash will be incorrect, and your application will break. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24 """ response = cherrypy.response # Guard against being run twice. if hasattr(response, "ETag"): return status, reason, msg = _http.valid_status(response.status) etag = response.headers.get('ETag') # Automatic ETag generation. See warning in docstring. if (not etag) and autotags: if status == 200: etag = response.collapse_body() etag = '"%s"' % md5(etag).hexdigest() response.headers['ETag'] = etag response.ETag = etag # "If the request would, without the If-Match header field, result in # anything other than a 2xx or 412 status, then the If-Match header # MUST be ignored." if status >= 200 and status <= 299: request = cherrypy.request conditions = request.headers.elements('If-Match') or [] conditions = [str(x) for x in conditions] if conditions and not (conditions == ["*"] or etag in conditions): raise cherrypy.HTTPError( 412, "If-Match failed: ETag %r did " "not match %r" % (etag, conditions)) conditions = request.headers.elements('If-None-Match') or [] conditions = [str(x) for x in conditions] if conditions == ["*"] or etag in conditions: if request.method in ("GET", "HEAD"): raise cherrypy.HTTPRedirect([], 304) else: raise cherrypy.HTTPError( 412, "If-None-Match failed: ETag %r " "matched %r" % (etag, conditions))
def validate_etags(autotags=False): """Validate the current ETag against If-Match, If-None-Match headers. If autotags is True, an ETag response-header value will be provided from an MD5 hash of the response body (unless some other code has already provided an ETag header). If False (the default), the ETag will not be automatic. WARNING: the autotags feature is not designed for URL's which allow methods other than GET. For example, if a POST to the same URL returns no content, the automatic ETag will be incorrect, breaking a fundamental use for entity tags in a possibly destructive fashion. Likewise, if you raise 304 Not Modified, the response body will be empty, the ETag hash will be incorrect, and your application will break. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24 """ response = cherrypy.response # Guard against being run twice. if hasattr(response, "ETag"): return status, reason, msg = _http.valid_status(response.status) etag = response.headers.get('ETag') # Automatic ETag generation. See warning in docstring. if (not etag) and autotags: if status == 200: etag = response.collapse_body() etag = '"%s"' % md5.new(etag).hexdigest() response.headers['ETag'] = etag response.ETag = etag # "If the request would, without the If-Match header field, result in # anything other than a 2xx or 412 status, then the If-Match header # MUST be ignored." if status >= 200 and status <= 299: request = cherrypy.request conditions = request.headers.elements('If-Match') or [] conditions = [str(x) for x in conditions] if conditions and not (conditions == ["*"] or etag in conditions): raise cherrypy.HTTPError(412, "If-Match failed: ETag %r did " "not match %r" % (etag, conditions)) conditions = request.headers.elements('If-None-Match') or [] conditions = [str(x) for x in conditions] if conditions == ["*"] or etag in conditions: if request.method in ("GET", "HEAD"): raise cherrypy.HTTPRedirect([], 304) else: raise cherrypy.HTTPError(412, "If-None-Match failed: ETag %r " "matched %r" % (etag, conditions))
def get_error_page(status, **kwargs): """Return an HTML page, containing a pretty error response. status should be an int or a str. kwargs will be interpolated into the page template. """ import cherrypy try: code, reason, message = _http.valid_status(status) except ValueError, x: raise cherrypy.HTTPError(500, x.args[0])
def finalize(self): """Transform headers (and cookies) into self.header_list. (Core)""" try: code, reason, _ = http.valid_status(self.status) except ValueError, x: raise cherrypy.HTTPError(500, x.args[0])
def __init__(self, status=500, message=None): self.status = status try: self.code, self.reason, defaultmsg = _http.valid_status(status) except ValueError, x: raise cherrypy.HTTPError(500, x.args[0])