Custom query extractor response
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Timo Ley 2022-01-11 19:42:15 +01:00
parent 614c23ca53
commit 1dbdc020b9
4 changed files with 36 additions and 12 deletions

View file

@ -1,2 +1 @@
- Port API to Rust
- Use IPFS as CDN
- Return API error response on missing query parameter

View file

@ -2,7 +2,7 @@ use std::convert::Infallible;
use axum::{
body::{Bytes, Full},
extract::multipart::MultipartError,
extract::{multipart::MultipartError, rejection::QueryRejection},
response::IntoResponse,
Json,
};
@ -28,6 +28,8 @@ pub enum APIError {
Internal(String),
#[error("IPFS error: {0}")]
Ipfs(#[from] IPFSError),
#[error("Query rejection: {0}")]
Query(#[from] QueryRejection),
}
impl ErrorResponse {
@ -59,6 +61,7 @@ impl IntoResponse for APIError {
ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Some(err))
}
APIError::Ipfs(_) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, None),
APIError::Query(_) => ErrorResponse::new(StatusCode::BAD_REQUEST, None),
};
let status = res.status;
(status, Json(res)).into_response()

View file

@ -3,4 +3,25 @@ pub mod models;
mod routes;
mod sql;
use async_trait::async_trait;
use axum::extract::{FromRequest, RequestParts};
pub use routes::routes;
use serde::de::DeserializeOwned;
use self::error::APIError;
pub struct Query<T>(pub T);
#[async_trait]
impl<T, B> FromRequest<B> for Query<T>
where
T: DeserializeOwned,
B: Send,
{
type Rejection = APIError;
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
let query = axum::extract::Query::<T>::from_request(req).await?;
Ok(Self(query.0))
}
}

View file

@ -3,7 +3,7 @@ use crate::ipfs::IPFSFile;
use crate::lib::ExtractIP;
use crate::v1::models::*;
use axum::extract::{ContentLengthLimit, Extension, Multipart, Query};
use axum::extract::{ContentLengthLimit, Extension, Multipart};
use axum::handler::{get, post};
use axum::response::IntoResponse;
use axum::routing::BoxRoute;
@ -12,9 +12,10 @@ use hyper::StatusCode;
use sqlx::MySqlPool;
use super::error::APIError;
use super::Query;
async fn meme(
params: Query<MemeIDQuery>,
Query(params): Query<MemeIDQuery>,
Extension(db_pool): Extension<MySqlPool>,
Extension(vars): Extension<ConfVars>,
) -> Result<impl IntoResponse, APIError> {
@ -27,11 +28,11 @@ async fn meme(
}
async fn memes(
params: Query<MemeFilterQuery>,
Query(params): Query<MemeFilterQuery>,
Extension(db_pool): Extension<MySqlPool>,
Extension(vars): Extension<ConfVars>,
) -> Result<impl IntoResponse, APIError> {
let memes = Meme::get_all(params.0, &db_pool, vars.cdn).await?;
let memes = Meme::get_all(params, &db_pool, vars.cdn).await?;
Ok(Json(MemesResponse {
status: 200,
error: None,
@ -40,7 +41,7 @@ async fn memes(
}
async fn category(
params: Query<IDQuery>,
Query(params): Query<IDQuery>,
Extension(db_pool): Extension<MySqlPool>,
) -> Result<impl IntoResponse, APIError> {
let category = Category::get(&params.id, &db_pool).await?;
@ -63,10 +64,10 @@ async fn categories(
}
async fn user(
params: Query<UserIDQuery>,
Query(params): Query<UserIDQuery>,
Extension(db_pool): Extension<MySqlPool>,
) -> Result<impl IntoResponse, APIError> {
let user = User::get(params.0, &db_pool).await?;
let user = User::get(params, &db_pool).await?;
Ok(Json(UserResponse {
status: 200,
error: None,
@ -84,11 +85,11 @@ async fn users(Extension(db_pool): Extension<MySqlPool>) -> Result<impl IntoResp
}
async fn random(
params: Query<MemeFilterQuery>,
Query(params): Query<MemeFilterQuery>,
Extension(db_pool): Extension<MySqlPool>,
Extension(vars): Extension<ConfVars>,
) -> Result<impl IntoResponse, APIError> {
let random = Meme::get_random(params.0, &db_pool, vars.cdn).await?;
let random = Meme::get_random(params, &db_pool, vars.cdn).await?;
Ok(Json(MemeResponse {
status: 200,
error: None,