v2: add pagination decorator
This commit is contained in:
parent
5b630ebdb0
commit
3f722f880e
6 changed files with 77 additions and 79 deletions
|
@ -2,13 +2,14 @@ import logging
|
|||
|
||||
from functools import wraps
|
||||
from urlparse import urlparse
|
||||
from urllib import urlencode
|
||||
|
||||
from flask import Blueprint, make_response, url_for, request, jsonify
|
||||
from semantic_version import Spec
|
||||
|
||||
import features
|
||||
|
||||
from app import app, metric_queue
|
||||
from app import app, metric_queue, get_app_url
|
||||
from auth.auth_context import get_grant_context
|
||||
from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission,
|
||||
AdministerRepositoryPermission)
|
||||
|
@ -19,12 +20,53 @@ from endpoints.v2.errors import V2RegistryException, Unauthorized
|
|||
from util.http import abort
|
||||
from util.registry.dockerver import docker_version
|
||||
from util.metrics.metricqueue import time_blueprint
|
||||
from util.pagination import encrypt_page_token, decrypt_page_token
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
v2_bp = Blueprint('v2', __name__)
|
||||
|
||||
time_blueprint(v2_bp, metric_queue)
|
||||
|
||||
|
||||
_MAX_RESULTS_PER_PAGE = 50
|
||||
|
||||
|
||||
def _paginate(limit_kwarg_name='limit', offset_kwarg_name='offset',
|
||||
callback_kwarg_name='pagination_callback'):
|
||||
def wrapper(func):
|
||||
@wraps(func)
|
||||
def wrapped(*args, **kwargs):
|
||||
try:
|
||||
requested_limit = int(request.args.get('n', _MAX_RESULTS_PER_PAGE))
|
||||
except ValueError:
|
||||
requested_limit = 0
|
||||
|
||||
limit = max(min(requested_limit, _MAX_RESULTS_PER_PAGE), 1)
|
||||
next_page_token = request.args.get('next_page', None)
|
||||
|
||||
# Decrypt the next page token, if any.
|
||||
offset = 0
|
||||
page_info = decrypt_page_token(next_page_token)
|
||||
if page_info is not None:
|
||||
# Note: we use offset here instead of ID >= n because one of the V2 queries is a UNION.
|
||||
offset = page_info.get('offset', 0)
|
||||
|
||||
def callback(num_results, response):
|
||||
if num_results <= limit:
|
||||
return
|
||||
next_page_token = encrypt_page_token({'offset': limit+offset})
|
||||
link = get_app_url() + url_for(request.endpoint, **request.view_args)
|
||||
link += '?%s; rel="next"' % urlencode({'n': limit, 'next_page': next_page_token})
|
||||
response.headers['Link'] = link
|
||||
|
||||
kwargs[limit_kwarg_name] = limit
|
||||
kwargs[offset_kwarg_name] = offset
|
||||
kwargs[callback_kwarg_name] = callback
|
||||
func(*args, **kwargs)
|
||||
return wrapped
|
||||
return wrapper
|
||||
|
||||
|
||||
@v2_bp.app_errorhandler(V2RegistryException)
|
||||
def handle_registry_v2_exception(error):
|
||||
response = jsonify({
|
||||
|
@ -104,8 +146,10 @@ def v2_support_enabled():
|
|||
return response
|
||||
|
||||
|
||||
from endpoints.v2 import v2auth
|
||||
from endpoints.v2 import manifest
|
||||
from endpoints.v2 import blob
|
||||
from endpoints.v2 import tag
|
||||
from endpoints.v2 import catalog
|
||||
from endpoints.v2 import (
|
||||
blob,
|
||||
catalog,
|
||||
manifest,
|
||||
tag,
|
||||
v2auth,
|
||||
)
|
||||
|
|
Reference in a new issue