Skip to content

Commit a5b5463

Browse files
author
Marco Napetti
committed
Paginate only when per_page parameter is present
1 parent 0db70a5 commit a5b5463

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

src/controllers/helpers/pagination.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl PaginationOptionsBuilder {
7373
self
7474
}
7575

76-
pub(crate) fn gather(self, req: &mut dyn RequestExt) -> AppResult<PaginationOptions> {
76+
pub(crate) fn gather(self, req: &dyn RequestExt) -> AppResult<PaginationOptions> {
7777
let params = req.query();
7878
let page_param = params.get("page");
7979
let seek_param = params.get("seek");
@@ -315,7 +315,7 @@ mod tests {
315315

316316
#[test]
317317
fn no_pagination_param() {
318-
let pagination = PaginationOptions::builder().gather(&mut mock("")).unwrap();
318+
let pagination = PaginationOptions::builder().gather(&mock("")).unwrap();
319319
assert_eq!(Page::Unspecified, pagination.page);
320320
assert_eq!(DEFAULT_PER_PAGE, pagination.per_page);
321321
}
@@ -331,7 +331,7 @@ mod tests {
331331
assert_error("page=0", "page indexing starts from 1, page 0 is invalid");
332332

333333
let pagination = PaginationOptions::builder()
334-
.gather(&mut mock("page=5"))
334+
.gather(&mock("page=5"))
335335
.unwrap();
336336
assert_eq!(Page::Numeric(5), pagination.page);
337337
}
@@ -347,7 +347,7 @@ mod tests {
347347
assert_error("per_page=101", "cannot request more than 100 items");
348348

349349
let pagination = PaginationOptions::builder()
350-
.gather(&mut mock("per_page=5"))
350+
.gather(&mock("per_page=5"))
351351
.unwrap();
352352
assert_eq!(5, pagination.per_page);
353353
}
@@ -362,7 +362,7 @@ mod tests {
362362

363363
let pagination = PaginationOptions::builder()
364364
.enable_seek(true)
365-
.gather(&mut mock("seek=OTg"))
365+
.gather(&mock("seek=OTg"))
366366
.unwrap();
367367

368368
if let Page::Seek(raw) = pagination.page {
@@ -420,7 +420,7 @@ mod tests {
420420

421421
fn assert_pagination_error(options: PaginationOptionsBuilder, query: &str, message: &str) {
422422
let response = options
423-
.gather(&mut mock(query))
423+
.gather(&mock(query))
424424
.unwrap_err()
425425
.response()
426426
.unwrap();

src/controllers/krate/metadata.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -326,20 +326,35 @@ pub fn readme(req: &mut dyn RequestExt) -> EndpointResult {
326326
// FIXME: Not sure why this is necessary since /crates/:crate_id returns
327327
// this information already, but ember is definitely requesting it
328328
pub fn versions(req: &mut dyn RequestExt) -> EndpointResult {
329-
let pagination_options = PaginationOptions::builder().gather(req)?;
330329
let crate_name = &req.params()["crate_id"];
331330
let conn = req.db_read()?;
332331
let krate: Crate = Crate::by_name(crate_name).first(&*conn)?;
333-
let data: Paginated<(Version, Option<User>)> = krate
334-
.all_versions()
335-
.left_outer_join(users::table)
336-
.select((versions::all_columns, users::all_columns.nullable()))
337-
.order(versions::created_at.desc())
338-
.pages_pagination(pagination_options)
339-
.load(&*conn)?;
340-
let more = data.next_page_params().is_some();
341332

342-
let mut versions_and_publishers = data.into_iter().collect::<Vec<_>>();
333+
// to keep retrocompatibility, we paginate only if per_page parameter is present
334+
let (mut versions_and_publishers, meta) = if req.query().get("per_page").is_some() {
335+
let pagination_options = PaginationOptions::builder().gather(req)?;
336+
let data: Paginated<(Version, Option<User>)> = krate
337+
.all_versions()
338+
.left_outer_join(users::table)
339+
.select((versions::all_columns, users::all_columns.nullable()))
340+
.order(versions::created_at.desc())
341+
.pages_pagination(pagination_options)
342+
.load(&*conn)?;
343+
let more = data.next_page_params().is_some();
344+
345+
(
346+
data.into_iter().collect::<Vec<_>>(),
347+
Some(json!({ "more": more })),
348+
)
349+
} else {
350+
let data: Vec<(Version, Option<User>)> = krate
351+
.all_versions()
352+
.left_outer_join(users::table)
353+
.select((versions::all_columns, users::all_columns.nullable()))
354+
.load(&*conn)?;
355+
(data, None)
356+
};
357+
343358
versions_and_publishers
344359
.sort_by_cached_key(|(version, _)| Reverse(semver::Version::parse(&version.num).ok()));
345360

@@ -354,10 +369,18 @@ pub fn versions(req: &mut dyn RequestExt) -> EndpointResult {
354369
.map(|((v, pb), aas)| EncodableVersion::from(v, crate_name, pb, aas))
355370
.collect::<Vec<_>>();
356371

357-
Ok(req.json(&json!({
358-
"versions": versions,
359-
"meta": { "more": more },
360-
})))
372+
// probably here would be simplier with a concrete response type
373+
let response = if let Some(meta) = meta {
374+
json!({
375+
"versions": versions,
376+
"meta": meta,
377+
})
378+
} else {
379+
json!({
380+
"versions": versions,
381+
})
382+
};
383+
Ok(req.json(&response))
361384
}
362385

363386
/// Handles the `GET /crates/:crate_id/reverse_dependencies` route.

0 commit comments

Comments
 (0)