Пример #1
0
def validate_etags(request, response, 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
    """

    # Guard against being run twice.
    if hasattr(response, "ETag"):
        return

    status, reason, msg = 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"' % hashlib.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:
        conditions = request.headers.elements('If-Match') or []
        conditions = [str(x) for x in conditions]
        if conditions and not (conditions == ["*"] or etag in conditions):
            return HTTPError(
                request, response, 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"):
                return Redirect(request, response, [], 304)
            else:
                return HTTPError(
                    request, response, 412,
                    "If-None-Match failed: ETag %r matched %r" %
                    (etag, conditions))
Пример #2
0
Файл: tools.py Проект: A-K/naali
def validate_etags(request, response, 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
    """
    
    # Guard against being run twice.
    if hasattr(response, "ETag"):
        return
    
    status, reason, msg = 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"' % hashlib.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:
        conditions = request.headers.elements('If-Match') or []
        conditions = [str(x) for x in conditions]
        if conditions and not (conditions == ["*"] or etag in conditions):
            return HTTPError(request, response, 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"):
                return Redirect(request, response, [], 304)
            else:
                return HTTPError(request, response, 412,
                        "If-None-Match failed: ETag %r matched %r" % (
                            etag, conditions))
Пример #3
0
def validate_since(request, response):
    """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.
    """

    lastmod = response.headers.get('Last-Modified')
    if lastmod:
        status, reason, msg = valid_status(response.status)

        since = request.headers.get('If-Unmodified-Since')
        if since and since != lastmod:
            if (status >= 200 and status <= 299) or status == 412:
                return HTTPError(request, response, 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"):
                    return Redirect(request, response, [], 304)
                else:
                    return HTTPError(request, response, 412)
Пример #4
0
def validate_since(request, response):
    """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.
    """

    lastmod = response.headers.get("Last-Modified")
    if lastmod:
        status, reason, msg = valid_status(response.status)

        since = request.headers.get("If-Unmodified-Since")
        if since and since != lastmod:
            if (status >= 200 and status <= 299) or status == 412:
                return HTTPError(request, response, 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"):
                    return Redirect(request, response, [], 304)
                else:
                    return HTTPError(request, response, 412)