Add default limit and max limit config vars

This commit is contained in:
Nathan Barber
2021-04-16 13:11:57 -04:00
parent 100111ed2c
commit 3c328385a4
6 changed files with 58 additions and 22 deletions

View File

@@ -108,7 +108,7 @@ paths:
description: |
Return a finite number of users.
Can be used with offset to paginate.
If unspecified, return all users.
If unspecified, use api_page_default_limit.
responses:
"200":
description: The Hub's user list
@@ -455,7 +455,7 @@ paths:
description: |
Return a finite number of groups.
Can be used with offset to paginate.
If unspecified, return all groups.
If unspecified, use api_page_default_limit.
responses:
"200":
description: The list of groups
@@ -487,7 +487,7 @@ paths:
description: |
Return a finite number of users within the given group.
Can be used with offset to paginate.
If unspecified, return all users.
If unspecified, use api_page_default_limit
responses:
"200":
description: The group model
@@ -610,7 +610,7 @@ paths:
description: |
Return a finite number of routes.
Can be used with offset to paginate.
If unspecified, return all routes.
If unspecified, use api_page_default_limit
responses:
"200":
description: Routing table

View File

@@ -175,6 +175,8 @@ r.raise_for_status()
r.json()
```
By default, pagination limit will be specified by the `JupyterHub.api_page_default_limit` config variable.
Pagination is enabled on the `GET /users`, `GET /groups`, `GET /groups/{name}`, and `GET /proxy` REST endpoints.
## Enabling users to spawn multiple named-servers via the API

View File

@@ -39,7 +39,8 @@ class GroupListAPIHandler(_GroupAPIHandler):
def get(self):
"""List groups"""
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", None)
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
query = self.db.query(orm.Group)
@@ -52,14 +53,18 @@ class GroupListAPIHandler(_GroupAPIHandler):
)
query = query.offset(offset)
if limit is not None:
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
query = query.limit(int(limit))
query = query.limit(limit)
data = [self.group_model(group) for group in query]
self.write(json.dumps(data))
@@ -100,13 +105,12 @@ class GroupAPIHandler(_GroupAPIHandler):
@admin_only
def get(self, name):
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", None)
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
group = self.find_group(name)
users_slice = None
print(type(group.users))
print(group.users)
if offset is not None:
try:
offset = int(offset)
@@ -117,15 +121,17 @@ class GroupAPIHandler(_GroupAPIHandler):
group.users = group.users[offset:]
if limit is not None:
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
group.users = group.users[:limit]
group.users = group.users[:limit]
group_model = self.group_model(group)

View File

@@ -18,7 +18,8 @@ class ProxyAPIHandler(APIHandler):
but without clients needing to maintain separate
"""
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", None)
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
routes = await self.proxy.get_all_routes()
@@ -35,16 +36,18 @@ class ProxyAPIHandler(APIHandler):
if key in routes
}
if limit is not None:
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
routes = {
key: routes[key] for key in list(routes.keys())[:limit] if key in routes
}
routes = {
key: routes[key] for key in list(routes.keys())[:limit] if key in routes
}
self.write(json.dumps(routes))

View File

@@ -56,7 +56,8 @@ class UserListAPIHandler(APIHandler):
def get(self):
state_filter = self.get_argument("state", None)
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", None)
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
# post_filter
post_filter = None
@@ -99,10 +100,25 @@ class UserListAPIHandler(APIHandler):
# Apply offset and limit for request pagination
if offset is not None:
query = query.offset(int(offset))
try:
offset = int(offset)
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, offset must be an integer"
)
query = query.offset(offset)
if limit is not None:
query = query.limit(int(limit))
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
query = query.limit(limit)
data = [
self.user_model(u, include_servers=True, include_state=True)

View File

@@ -936,6 +936,15 @@ class JupyterHub(Application):
""",
).tag(config=True)
api_page_default_limit = Integer(
50,
help="The default amount of records returned by a paginated endpoint",
).tag(config=True)
api_page_max_limit = Integer(
200, help="The maximum amount of records that can be returned at once"
)
authenticate_prometheus = Bool(
True, help="Authentication for prometheus metrics"
).tag(config=True)