diff --git a/src/controllers/keyword.rs b/src/controllers/keyword.rs index bce90acd46f..1f7937b99a2 100644 --- a/src/controllers/keyword.rs +++ b/src/controllers/keyword.rs @@ -1,17 +1,24 @@ use crate::app::AppState; -use crate::controllers::helpers::pagination::PaginationOptions; +use crate::controllers::helpers::pagination::{PaginationOptions, PaginationQueryParams}; use crate::controllers::helpers::{Paginate, pagination::Paginated}; use crate::models::Keyword; use crate::util::errors::AppResult; use crate::views::EncodableKeyword; -use axum::extract::{Path, Query}; +use axum::extract::{FromRequestParts, Path, Query}; use axum_extra::json; use axum_extra::response::ErasedJson; use diesel::prelude::*; use http::request::Parts; -#[derive(Deserialize)] -pub struct IndexQuery { +#[derive(Debug, Deserialize, FromRequestParts, utoipa::IntoParams)] +#[from_request(via(Query))] +#[into_params(parameter_in = Query)] +pub struct ListQueryParams { + /// The sort order of the keywords. + /// + /// Valid values: `alpha`, and `crates`. + /// + /// Defaults to `alpha`. sort: Option, } @@ -19,19 +26,20 @@ pub struct IndexQuery { #[utoipa::path( get, path = "/api/v1/keywords", + params(ListQueryParams, PaginationQueryParams), tag = "keywords", responses((status = 200, description = "Successful Response")), )] pub async fn list_keywords( state: AppState, - qp: Query, + params: ListQueryParams, req: Parts, ) -> AppResult { use crate::schema::keywords; let mut query = keywords::table.into_boxed(); - query = match &qp.sort { + query = match ¶ms.sort { Some(sort) if sort == "crates" => query.order(keywords::crates_cnt.desc()), _ => query.order(keywords::keyword.asc()), }; diff --git a/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap b/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap index c32ab7d2c54..abf35a1c61e 100644 --- a/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap +++ b/src/snapshots/crates_io__openapi__tests__openapi_snapshot.snap @@ -1287,6 +1287,48 @@ expression: response.json() "/api/v1/keywords": { "get": { "operationId": "list_keywords", + "parameters": [ + { + "description": "The sort order of the keywords.\n\nValid values: `alpha`, and `crates`.\n\nDefaults to `alpha`.", + "in": "query", + "name": "sort", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "The page number to request.\n\nThis parameter is mutually exclusive with `seek` and not supported for\nall requests.", + "in": "query", + "name": "page", + "required": false, + "schema": { + "format": "int32", + "minimum": 1, + "type": "integer" + } + }, + { + "description": "The number of items to request per page.", + "in": "query", + "name": "per_page", + "required": false, + "schema": { + "format": "int32", + "minimum": 1, + "type": "integer" + } + }, + { + "description": "The seek key to request.\n\nThis parameter is mutually exclusive with `page` and not supported for\nall requests.\n\nThe seek key can usually be found in the `meta.next_page` field of\npaginated responses.", + "in": "query", + "name": "seek", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "Successful Response"