Пример #1
0
 def test_etags(self):
     assert http.quote_etag('foo') == '"foo"'
     assert http.quote_etag('foo', True) == 'W/"foo"'
     assert http.unquote_etag('"foo"') == ('foo', False)
     assert http.unquote_etag('W/"foo"') == ('foo', True)
     es = http.parse_etags('"foo", "bar", W/"baz", blar')
     assert sorted(es) == ['bar', 'blar', 'foo']
     assert 'foo' in es
     assert 'baz' not in es
     assert es.contains_weak('baz')
     assert 'blar' in es
     assert es.contains_raw('W/"baz"')
     assert es.contains_raw('"foo"')
     assert sorted(es.to_header().split(', ')) == ['"bar"', '"blar"', '"foo"', 'W/"baz"']
Пример #2
0
 def test_etags(self):
     assert http.quote_etag('foo') == '"foo"'
     assert http.quote_etag('foo', True) == 'w/"foo"'
     assert http.unquote_etag('"foo"') == ('foo', False)
     assert http.unquote_etag('w/"foo"') == ('foo', True)
     es = http.parse_etags('"foo", "bar", w/"baz", blar')
     assert sorted(es) == ['bar', 'blar', 'foo']
     assert 'foo' in es
     assert 'baz' not in es
     assert es.contains_weak('baz')
     assert 'blar' in es
     assert es.contains_raw('w/"baz"')
     assert es.contains_raw('"foo"')
     assert sorted(es.to_header().split(', ')) == ['"bar"', '"blar"', '"foo"', 'w/"baz"']
Пример #3
0
 def test_etags(self):
     assert http.quote_etag("foo") == '"foo"'
     assert http.quote_etag("foo", True) == 'w/"foo"'
     assert http.unquote_etag('"foo"') == ("foo", False)
     assert http.unquote_etag('w/"foo"') == ("foo", True)
     es = http.parse_etags('"foo", "bar", w/"baz", blar')
     assert sorted(es) == ["bar", "blar", "foo"]
     assert "foo" in es
     assert "baz" not in es
     assert es.contains_weak("baz")
     assert "blar" in es
     assert es.contains_raw('w/"baz"')
     assert es.contains_raw('"foo"')
     assert sorted(es.to_header().split(", ")) == ['"bar"', '"blar"', '"foo"', 'w/"baz"']
Пример #4
0
    def test_exception_header_forwarded(self):
        """Test that HTTPException's headers are extended properly"""
        app = Flask(__name__)
        app.config['DEBUG'] = True
        api = flask_restful.Api(app)

        class NotModified(HTTPException):
            code = 304

            def __init__(self, etag, *args, **kwargs):
                super(NotModified, self).__init__(*args, **kwargs)
                self.etag = quote_etag(etag)

            def get_headers(self, *args, **kwargs):
                """Get a list of headers."""
                return [('ETag', self.etag)]

        class Foo1(flask_restful.Resource):
            def get(self):
                flask_abort(304, etag='myETag')

        api.add_resource(Foo1, '/foo')
        _aborter.mapping.update({304: NotModified})

        with app.test_client() as client:
            foo = client.get('/foo')
            self.assertEquals(foo.get_etag(),
                              unquote_etag(quote_etag('myETag')))
Пример #5
0
def feed(config, tz, template, page=None):
    include_day = config.include_day
    start = datetime.fromtimestamp(config.start_timestamp, tz)
    now = datetime.now(start.tzinfo)

    total_posts = count_dates(start, now, include_day)
    per_page = 50
    last_page = total_posts // per_page - 1

    headers = {
        'Date': http_date(now),
    }

    links = []
    if page is None:
        etag = quote_etag(str(total_posts))
        next_date, dates = recent_dates(start, now, include_day, per_page)
        max_age = int((next_date - now).total_seconds())
        if last_page >= 0:
            links.append(('prev-archive', last_page))
    elif page <= last_page:
        etag = '"0"'
        dates = archived_dates(start, include_day, page * per_page, per_page)
        max_age = 7 * 24 * 60 * 60
        links.append(('current', None))
        if page < last_page:
            links.append(('next-archive', page + 1))
        if page > 0:
            links.append(('prev-archive', page - 1))
    else:
        abort(404)

    headers['Cache-Control'] = "public, max-age={}, immutable".format(max_age)
    headers['Expires'] = http_date(now + timedelta(seconds=max_age))
    headers['ETag'] = etag
    if not is_resource_modified(request.environ, etag):
        return Response(status=304, headers=headers)

    day_names = [
        calendar.day_name[day] for day, included in enumerate(include_day)
        if included
    ]
    if len(day_names) > 1:
        days_description = '{} and {}'.format(
            ', '.join(day_names[:-1]),
            day_names[-1],
        )
    else:
        days_description = day_names[0]

    feed = render_template(
        "feed.xml",
        template=template,
        days_description=days_description,
        start=start,
        config=config,
        links=links,
        dates=dates,
    )
    return Response(feed, mimetype='application/rss+xml', headers=headers)
Пример #6
0
    def response(self, request, data, etag=None, cache_policy=None):
        """Renders `data` to a JSON response.

        An ETag may be specified. When it is not specified one will be generated
        based on the data.

        The caching policy can be optionally configured. By default it takes the
        policy from the controller object: `cache_policy`.
        """
        if etag is None and data is not None:
            etag = self.etag(data)
        # FIXME: Check content-type headers
        if data is None:
            if etag is None:
                raise TypeError('response requires an etag when '
                                'the response body is None')
            resp = Response(status=304, content_type='application/json')
        else:
            # Avoid sending the resource when an ETag matches
            request_etags = parse_etags(
                request.environ.get('HTTP_IF_NONE_MATCH'))
            if request_etags.contains(etag):
                 resp = Response(status=304, content_type='application/json')
            # Render the given data to a response object
            else:
                resp = Response(self.data_encoder.encode(data), content_type='application/json')
        resp.headers['ETag'] = quote_etag(etag)
        if cache_policy is None:
            cache_policy = self.cache_policy
        return cache_policy(resp)
Пример #7
0
    def build_etag(self, response, include_etag=True, **kwargs):
        """
        Add an etag to the response body.

        Uses spooky where possible because it is empirically fast and well-regarded.

        See: http://blog.reverberate.org/2012/01/state-of-hash-functions-2012.html

        """
        if not include_etag:
            return

        if not spooky:
            # use built-in md5
            response.add_etag()
            return

        # use spooky
        response.headers["ETag"] = quote_etag(
            hexlify(
                spooky.hash128(
                    response.get_data(),
                ).to_bytes(16, "little"),
            ).decode("utf-8"),
        )
Пример #8
0
    def test_exception_header_forwarded(self):
        '''Ensure that HTTPException's headers are extended properly'''
        self.app.config['DEBUG'] = True
        api = restplus.Api(self.app)

        class NotModified(HTTPException):
            code = 304

            def __init__(self, etag, *args, **kwargs):
                super(NotModified, self).__init__(*args, **kwargs)
                self.etag = quote_etag(etag)

            def get_headers(self, *args, **kwargs):
                return [('ETag', self.etag)]

        @api.route('/foo')
        class Foo1(restplus.Resource):
            def get(self):
                abort(304, etag='myETag')

        abort.mapping.update({304: NotModified})

        with self.app.test_client() as client:
            foo = client.get('/foo')
            self.assertEquals(foo.get_etag(),
                              unquote_etag(quote_etag('myETag')))
 def make_headers(self, content=None):
     """Add `ETag` header to response."""
     headers = super().make_headers(content=content)
     etag = content.get("revision_id") if content else None
     if etag:
         headers["ETag"] = quote_etag(str(etag), False)
     return headers
Пример #10
0
    def test_exception_header_forwarded(self):
        """Test that HTTPException's headers are extended properly"""
        app = Flask(__name__)
        app.config['DEBUG'] = True
        api = flask_restful.Api(app)

        class NotModified(HTTPException):
            code = 304

            def __init__(self, etag, *args, **kwargs):
                super(NotModified, self).__init__(*args, **kwargs)
                self.etag = quote_etag(etag)

            def get_headers(self, *args, **kwargs):
                """Get a list of headers."""
                return [('ETag', self.etag)]

        class Foo1(flask_restful.Resource):
            def get(self):
                flask_abort(304, etag='myETag')

        api.add_resource(Foo1, '/foo')
        flask_abort.mapping.update({304: NotModified})

        with app.test_client() as client:
            foo = client.get('/foo')
            self.assertEquals(foo.get_etag(),
                              unquote_etag(quote_etag('myETag')))
Пример #11
0
    def build_etag(self, response, include_etag=True, **kwargs):
        """
        Add an etag to the response body.

        Uses spooky where possible because it is empirically fast and well-regarded.

        See: http://blog.reverberate.org/2012/01/state-of-hash-functions-2012.html

        """
        if not include_etag:
            return

        if not spooky:
            # use built-in md5
            response.add_etag()
            return

        # use spooky
        response.headers["ETag"] = quote_etag(
            hexlify(
                spooky.hash128(
                    response.get_data(),
                ).to_bytes(16, "little"),
            ).decode("utf-8"),
        )
    def test_exception_header_forwarded(self):
        '''Ensure that HTTPException's headers are extended properly'''
        self.app.config['DEBUG'] = True
        api = restplus.Api(self.app)

        class NotModified(HTTPException):
            code = 304

            def __init__(self, etag, *args, **kwargs):
                super(NotModified, self).__init__(*args, **kwargs)
                self.etag = quote_etag(etag)

            def get_headers(self, *args, **kwargs):
                return [('ETag', self.etag)]

        @api.route('/foo')
        class Foo1(restplus.Resource):
            def get(self):
                abort(304, etag='myETag')

        abort.mapping.update({304: NotModified})

        with self.app.test_client() as client:
            foo = client.get('/foo')
            self.assertEquals(foo.get_etag(),
                              unquote_etag(quote_etag('myETag')))
Пример #13
0
 def test_etags(self):
     assert http.quote_etag("foo") == '"foo"'
     assert http.quote_etag("foo", True) == 'W/"foo"'
     assert http.unquote_etag('"foo"') == ("foo", False)
     assert http.unquote_etag('W/"foo"') == ("foo", True)
     es = http.parse_etags('"foo", "bar", W/"baz", blar')
     assert sorted(es) == ["bar", "blar", "foo"]
     assert "foo" in es
     assert "baz" not in es
     assert es.contains_weak("baz")
     assert "blar" in es
     assert es.contains_raw('W/"baz"')
     assert es.contains_raw('"foo"')
     assert sorted(es.to_header().split(", ")) == [
         '"bar"',
         '"blar"',
         '"foo"',
         'W/"baz"',
     ]
Пример #14
0
 def check_normal_response(res, method):
     if method != client.head:
         parsed = json.loads(res.get_data(as_text=True))
         expected = {'id': 1, 'method': parsed['method']}
         assert parsed == expected
         # check that the right method was called
         assert method_names[parsed['method']] == method
         assert res.content_type == 'application/json'
     assert res.status_code == 200
     # check that the ETag is correct
     assert unquote_etag(res.headers['ETag']) == \
         unquote_etag(quote_etag('abc'))
Пример #15
0
 def check_normal_response(res, method):
     if method != client.head:
         parsed = json.loads(res.get_data(as_text=True))
         expected = {'id': 1, 'method': parsed['method']}
         assert parsed == expected
         # check that the right method was called
         assert method_names[parsed['method']] == method
         assert res.content_type == 'application/json'
     assert res.status_code == 200
     # check that the ETag is correct
     assert unquote_etag(res.headers['ETag']) == \
         unquote_etag(quote_etag('abc'))
Пример #16
0
def etag_headers(obj_or_list, code, many=False):
    """Headers for a single resource item."""
    headers = {
        'content-type': resource_requestctx.accept_mimetype,
    }
    if many:
        return headers

    etag = obj_or_list.get("revision_id")
    if etag:
        headers["ETag"] = quote_etag(str(etag), False)
    return headers
Пример #17
0
def serve_file(path):
    headers = {}

    st = os.stat(path)

    etag = 'clay-{0}-{1}-{2}'.format(
        os.path.getmtime(path), os.path.getsize(path),
        adler32(path.encode('utf-8')) & 0xffffffff)
    headers['ETag'] = quote_etag(etag)

    # Set the Last-Modified response header, so that
    # modified-since validation code can work.
    headers['Last-Modified'] = httputil.HTTPDate(st.st_mtime)

    _, ext = os.path.splitext(path)
    content_type = mimetypes.types_map.get(ext, None)
    headers['Content-Type'] = content_type or 'text/plain'

    fileobj = open(path, 'rb')
    return serve_fileobj(fileobj, headers, st.st_size)
Пример #18
0
def serve_file(path):
    headers = {}

    st = os.stat(path)

    etag = 'clay-{0}-{1}-{2}'.format(
        os.path.getmtime(path),
        os.path.getsize(path),
        adler32(path.encode('utf-8')) & 0xffffffff
    )
    headers['ETag'] = quote_etag(etag)

    # Set the Last-Modified response header, so that
    # modified-since validation code can work.
    headers['Last-Modified'] = httputil.HTTPDate(st.st_mtime)

    _, ext = os.path.splitext(path)
    content_type = mimetypes.types_map.get(ext, None)
    headers['Content-Type'] = content_type or 'text/plain'

    fileobj = open(path, 'rb')
    return serve_fileobj(fileobj, headers, st.st_size)
Пример #19
0
    def test_exception_header_forwarded(self, app, client):
        '''Ensure that HTTPException's headers are extended properly'''
        api = restplus.Api(app)

        class NotModified(HTTPException):
            code = 304

            def __init__(self, etag, *args, **kwargs):
                super(NotModified, self).__init__(*args, **kwargs)
                self.etag = quote_etag(etag)

            def get_headers(self, *args, **kwargs):
                return [('ETag', self.etag)]

        custom_abort = Aborter(mapping={304: NotModified})

        @api.route('/foo')
        class Foo1(restplus.Resource):
            def get(self):
                custom_abort(304, etag='myETag')

        foo = client.get('/foo')
        assert foo.get_etag() == unquote_etag(quote_etag('myETag'))
Пример #20
0
    def test_exception_header_forwarded(self, app, client):
        '''Ensure that HTTPException's headers are extended properly'''
        api = restplus.Api(app)

        class NotModified(HTTPException):
            code = 304

            def __init__(self, etag, *args, **kwargs):
                super(NotModified, self).__init__(*args, **kwargs)
                self.etag = quote_etag(etag)

            def get_headers(self, *args, **kwargs):
                return [('ETag', self.etag)]

        custom_abort = Aborter(mapping={304: NotModified})

        @api.route('/foo')
        class Foo1(restplus.Resource):
            def get(self):
                custom_abort(304, etag='myETag')

        foo = client.get('/foo')
        assert foo.get_etag() == unquote_etag(quote_etag('myETag'))
Пример #21
0
 def set_etag(self, etag, weak = False):
     self.headers['ETag'] = quote_etag(etag, weak)
Пример #22
0
 def __init__(self, etag, *args, **kwargs):
     super(NotModified, self).__init__(*args, **kwargs)
     self.etag = quote_etag(etag)
Пример #23
0
 def check_304_response(res):
     assert res.status_code == 304
     # check that the ETag is correct
     assert unquote_etag(res.headers['ETag']) == \
         unquote_etag(quote_etag('abc'))
Пример #24
0
 def __init__(self, etag, *args, **kwargs):
     super(NotModified, self).__init__(*args, **kwargs)
     self.etag = quote_etag(etag)
Пример #25
0
 def set_etag(self, etag: str, weak: bool = False) -> None:
     """Set the etag, and override the old one if there was one."""
     self.headers["ETag"] = quote_etag(etag, weak)
Пример #26
0
 def check_304_response(res):
     assert res.status_code == 304
     # check that the ETag is correct
     assert unquote_etag(res.headers['ETag']) == \
         unquote_etag(quote_etag('abc'))
Пример #27
0
 def set_etag(self, etag, weak=False):
     """Set the etag, and override the old one if there was one."""
     self.headers['ETag'] = quote_etag(etag, weak)
Пример #28
0
 def set_etag(self, etag, weak = False):
     self.headers['ETag'] = quote_etag(etag, weak)