Custom query extractor response
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
614c23ca53
commit
1dbdc020b9
4 changed files with 36 additions and 12 deletions
|
@ -1,2 +1 @@
|
||||||
- Port API to Rust
|
- Return API error response on missing query parameter
|
||||||
- Use IPFS as CDN
|
|
|
@ -2,7 +2,7 @@ use std::convert::Infallible;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::{Bytes, Full},
|
body::{Bytes, Full},
|
||||||
extract::multipart::MultipartError,
|
extract::{multipart::MultipartError, rejection::QueryRejection},
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
Json,
|
Json,
|
||||||
};
|
};
|
||||||
|
@ -28,6 +28,8 @@ pub enum APIError {
|
||||||
Internal(String),
|
Internal(String),
|
||||||
#[error("IPFS error: {0}")]
|
#[error("IPFS error: {0}")]
|
||||||
Ipfs(#[from] IPFSError),
|
Ipfs(#[from] IPFSError),
|
||||||
|
#[error("Query rejection: {0}")]
|
||||||
|
Query(#[from] QueryRejection),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorResponse {
|
impl ErrorResponse {
|
||||||
|
@ -59,6 +61,7 @@ impl IntoResponse for APIError {
|
||||||
ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Some(err))
|
ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Some(err))
|
||||||
}
|
}
|
||||||
APIError::Ipfs(_) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, None),
|
APIError::Ipfs(_) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, None),
|
||||||
|
APIError::Query(_) => ErrorResponse::new(StatusCode::BAD_REQUEST, None),
|
||||||
};
|
};
|
||||||
let status = res.status;
|
let status = res.status;
|
||||||
(status, Json(res)).into_response()
|
(status, Json(res)).into_response()
|
||||||
|
|
|
@ -3,4 +3,25 @@ pub mod models;
|
||||||
mod routes;
|
mod routes;
|
||||||
mod sql;
|
mod sql;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use axum::extract::{FromRequest, RequestParts};
|
||||||
pub use routes::routes;
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::ipfs::IPFSFile;
|
||||||
use crate::lib::ExtractIP;
|
use crate::lib::ExtractIP;
|
||||||
use crate::v1::models::*;
|
use crate::v1::models::*;
|
||||||
|
|
||||||
use axum::extract::{ContentLengthLimit, Extension, Multipart, Query};
|
use axum::extract::{ContentLengthLimit, Extension, Multipart};
|
||||||
use axum::handler::{get, post};
|
use axum::handler::{get, post};
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::routing::BoxRoute;
|
use axum::routing::BoxRoute;
|
||||||
|
@ -12,9 +12,10 @@ use hyper::StatusCode;
|
||||||
use sqlx::MySqlPool;
|
use sqlx::MySqlPool;
|
||||||
|
|
||||||
use super::error::APIError;
|
use super::error::APIError;
|
||||||
|
use super::Query;
|
||||||
|
|
||||||
async fn meme(
|
async fn meme(
|
||||||
params: Query<MemeIDQuery>,
|
Query(params): Query<MemeIDQuery>,
|
||||||
Extension(db_pool): Extension<MySqlPool>,
|
Extension(db_pool): Extension<MySqlPool>,
|
||||||
Extension(vars): Extension<ConfVars>,
|
Extension(vars): Extension<ConfVars>,
|
||||||
) -> Result<impl IntoResponse, APIError> {
|
) -> Result<impl IntoResponse, APIError> {
|
||||||
|
@ -27,11 +28,11 @@ async fn meme(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn memes(
|
async fn memes(
|
||||||
params: Query<MemeFilterQuery>,
|
Query(params): Query<MemeFilterQuery>,
|
||||||
Extension(db_pool): Extension<MySqlPool>,
|
Extension(db_pool): Extension<MySqlPool>,
|
||||||
Extension(vars): Extension<ConfVars>,
|
Extension(vars): Extension<ConfVars>,
|
||||||
) -> Result<impl IntoResponse, APIError> {
|
) -> 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 {
|
Ok(Json(MemesResponse {
|
||||||
status: 200,
|
status: 200,
|
||||||
error: None,
|
error: None,
|
||||||
|
@ -40,7 +41,7 @@ async fn memes(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn category(
|
async fn category(
|
||||||
params: Query<IDQuery>,
|
Query(params): Query<IDQuery>,
|
||||||
Extension(db_pool): Extension<MySqlPool>,
|
Extension(db_pool): Extension<MySqlPool>,
|
||||||
) -> Result<impl IntoResponse, APIError> {
|
) -> Result<impl IntoResponse, APIError> {
|
||||||
let category = Category::get(¶ms.id, &db_pool).await?;
|
let category = Category::get(¶ms.id, &db_pool).await?;
|
||||||
|
@ -63,10 +64,10 @@ async fn categories(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn user(
|
async fn user(
|
||||||
params: Query<UserIDQuery>,
|
Query(params): Query<UserIDQuery>,
|
||||||
Extension(db_pool): Extension<MySqlPool>,
|
Extension(db_pool): Extension<MySqlPool>,
|
||||||
) -> Result<impl IntoResponse, APIError> {
|
) -> Result<impl IntoResponse, APIError> {
|
||||||
let user = User::get(params.0, &db_pool).await?;
|
let user = User::get(params, &db_pool).await?;
|
||||||
Ok(Json(UserResponse {
|
Ok(Json(UserResponse {
|
||||||
status: 200,
|
status: 200,
|
||||||
error: None,
|
error: None,
|
||||||
|
@ -84,11 +85,11 @@ async fn users(Extension(db_pool): Extension<MySqlPool>) -> Result<impl IntoResp
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn random(
|
async fn random(
|
||||||
params: Query<MemeFilterQuery>,
|
Query(params): Query<MemeFilterQuery>,
|
||||||
Extension(db_pool): Extension<MySqlPool>,
|
Extension(db_pool): Extension<MySqlPool>,
|
||||||
Extension(vars): Extension<ConfVars>,
|
Extension(vars): Extension<ConfVars>,
|
||||||
) -> Result<impl IntoResponse, APIError> {
|
) -> 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 {
|
Ok(Json(MemeResponse {
|
||||||
status: 200,
|
status: 200,
|
||||||
error: None,
|
error: None,
|
||||||
|
|
Loading…
Reference in a new issue