chore: update everything to work with utoipa
This commit is contained in:
@@ -47,20 +47,23 @@ revolt-files = { version = "0.8.9", path = "../../core/files" }
|
||||
revolt-config = { version = "0.8.9", path = "../../core/config" }
|
||||
revolt-database = { version = "0.8.9", path = "../../core/database", features = [
|
||||
"axum-impl",
|
||||
"utoipa",
|
||||
] }
|
||||
revolt-result = { version = "0.8.9", path = "../../core/result", features = [
|
||||
"utoipa",
|
||||
"axum",
|
||||
] }
|
||||
revolt-ratelimits = { version = "0.8.9", path = "../../core/ratelimits", features = ["axum"] }
|
||||
revolt-ratelimits = { version = "0.8.9", path = "../../core/ratelimits", features = [
|
||||
"axum",
|
||||
] }
|
||||
|
||||
# Axum / web server
|
||||
tempfile = "3.12.0"
|
||||
axum-macros = "0.4.1"
|
||||
axum_typed_multipart = "0.12.1"
|
||||
axum = { version = "0.7.5", features = ["multipart"] }
|
||||
axum-macros = "0.5.0"
|
||||
axum_typed_multipart = "0.16.4"
|
||||
axum = { version = "0.8.6", features = ["multipart"] }
|
||||
tower-http = { version = "0.5.2", features = ["cors"] }
|
||||
|
||||
# OpenAPI & documentation generation
|
||||
utoipa-scalar = { version = "0.1.0", features = ["axum"] }
|
||||
utoipa = { version = "4.2.3", features = ["axum_extras", "ulid"] }
|
||||
utoipa-scalar = { version = "0.3.0", features = ["axum"] }
|
||||
utoipa = { version = "5.4.0", features = ["ulid"] }
|
||||
|
||||
@@ -23,9 +23,14 @@ use sha2::Digest;
|
||||
use tempfile::NamedTempFile;
|
||||
use tokio::time::Instant;
|
||||
use tower_http::cors::{AllowHeaders, Any, CorsLayer};
|
||||
use utoipa::ToSchema;
|
||||
use utoipa::{
|
||||
openapi::{schema::ObjectBuilder, SchemaFormat},
|
||||
PartialSchema, ToSchema,
|
||||
};
|
||||
|
||||
use crate::{exif::strip_metadata, metadata::generate_metadata, mime_type::determine_mime_type, AppState};
|
||||
use crate::{
|
||||
exif::strip_metadata, metadata::generate_metadata, mime_type::determine_mime_type, AppState,
|
||||
};
|
||||
|
||||
/// Build the API router
|
||||
pub async fn router() -> Router<AppState> {
|
||||
@@ -122,14 +127,32 @@ pub enum Tag {
|
||||
}
|
||||
|
||||
/// Request body for upload
|
||||
#[derive(ToSchema, TryFromMultipart)]
|
||||
#[derive(TryFromMultipart)]
|
||||
pub struct UploadPayload {
|
||||
#[schema(format = Binary)]
|
||||
#[allow(dead_code)]
|
||||
#[form_data(limit = "unlimited")] // handled by axum
|
||||
file: FieldData<NamedTempFile>,
|
||||
}
|
||||
|
||||
impl ToSchema for UploadPayload {
|
||||
fn name() -> std::borrow::Cow<'static, str> {
|
||||
std::borrow::Cow::Borrowed("UploadPayload")
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialSchema for UploadPayload {
|
||||
fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
|
||||
ObjectBuilder::new()
|
||||
.property(
|
||||
"file",
|
||||
ObjectBuilder::new().format(Some(SchemaFormat::KnownFormat(
|
||||
utoipa::openapi::KnownFormat::Binary,
|
||||
))),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Successful upload response
|
||||
#[derive(Serialize, Debug, ToSchema)]
|
||||
pub struct UploadResponse {
|
||||
@@ -160,8 +183,8 @@ pub struct UploadResponse {
|
||||
),
|
||||
request_body(content_type = "multipart/form-data", content = UploadPayload),
|
||||
security(
|
||||
("session_token" = []),
|
||||
("bot_token" = [])
|
||||
("Session-Token" = []),
|
||||
("Bot-Token" = [])
|
||||
)
|
||||
)]
|
||||
async fn upload_file(
|
||||
|
||||
@@ -3,13 +3,10 @@ use std::net::{Ipv4Addr, SocketAddr};
|
||||
use axum::{middleware::from_fn_with_state, Router};
|
||||
|
||||
use axum_macros::FromRef;
|
||||
use revolt_database::{Database, DatabaseInfo};
|
||||
use revolt_database::{Database, DatabaseInfo, User, util::utoipa::TokenSecurity};
|
||||
use revolt_ratelimits::axum as ratelimiter;
|
||||
use tokio::net::TcpListener;
|
||||
use utoipa::{
|
||||
openapi::security::{ApiKey, ApiKeyValue, SecurityScheme},
|
||||
Modify, OpenApi,
|
||||
};
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_scalar::{Scalar, Servable as ScalarServable};
|
||||
|
||||
mod api;
|
||||
@@ -36,7 +33,7 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
// Configure API schema
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
modifiers(&SecurityAddon),
|
||||
modifiers(&TokenSecurity),
|
||||
paths(
|
||||
api::root,
|
||||
api::upload_file,
|
||||
@@ -59,23 +56,6 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
)]
|
||||
struct ApiDoc;
|
||||
|
||||
struct SecurityAddon;
|
||||
|
||||
impl Modify for SecurityAddon {
|
||||
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
||||
if let Some(components) = openapi.components.as_mut() {
|
||||
components.add_security_scheme(
|
||||
"bot_token",
|
||||
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new("X-Bot-Token"))),
|
||||
);
|
||||
components.add_security_scheme(
|
||||
"session_token",
|
||||
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new("X-Session-Token"))),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to the database
|
||||
let db = DatabaseInfo::Auto.connect().await.unwrap();
|
||||
let ratelimits = ratelimiter::RatelimitStorage::new(ratelimits::AutumnRatelimits);
|
||||
|
||||
@@ -33,12 +33,12 @@ revolt-ratelimits = { version = "0.8.9", path = "../../core/ratelimits", feature
|
||||
] }
|
||||
|
||||
# Axum / web server
|
||||
axum = { version = "0.7.5" }
|
||||
axum-extra = { version = "0.9", features = ["typed-header"] }
|
||||
axum = { version = "0.8.6" }
|
||||
axum-extra = { version = "0.12.1", features = ["typed-header"] }
|
||||
|
||||
# OpenAPI & documentation generation
|
||||
utoipa-scalar = { version = "0.1.0", features = ["axum"] }
|
||||
utoipa = { version = "4.2.3", features = ["axum_extras", "ulid"] }
|
||||
utoipa-scalar = { version = "0.3.0", features = ["axum"] }
|
||||
utoipa = { version = "5.4.0", features = ["ulid"] }
|
||||
|
||||
# Logging
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
use axum::{extract::FromRef, middleware::from_fn_with_state, Router};
|
||||
use axum::{
|
||||
extract::FromRef, middleware::from_fn_with_state, Router,
|
||||
};
|
||||
|
||||
use revolt_config::config;
|
||||
use revolt_database::{Database, DatabaseInfo};
|
||||
use revolt_database::{Database, DatabaseInfo, util::utoipa::TokenSecurity};
|
||||
use revolt_ratelimits::axum as ratelimiter;
|
||||
use tokio::net::TcpListener;
|
||||
use utoipa::{
|
||||
openapi::security::{ApiKey, ApiKeyValue, SecurityScheme},
|
||||
Modify, OpenApi,
|
||||
};
|
||||
use utoipa_scalar::{Scalar, Servable as ScalarServable};
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_scalar::{Scalar, Servable};
|
||||
|
||||
use crate::tenor::Tenor;
|
||||
|
||||
@@ -26,26 +25,6 @@ struct AppState {
|
||||
pub ratelimit_storage: ratelimiter::RatelimitStorage,
|
||||
}
|
||||
|
||||
struct SecurityAddon;
|
||||
|
||||
impl Modify for SecurityAddon {
|
||||
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
||||
let components = openapi.components.get_or_insert_default();
|
||||
|
||||
components.add_security_scheme(
|
||||
"User Token",
|
||||
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new(
|
||||
"X-Session-Token".to_string(),
|
||||
))),
|
||||
);
|
||||
|
||||
components.add_security_scheme(
|
||||
"Bot Token",
|
||||
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new("X-Bot-Token".to_string()))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
// Configure logging and environment
|
||||
@@ -54,7 +33,7 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
// Configure API schema
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
modifiers(&SecurityAddon),
|
||||
modifiers(&TokenSecurity),
|
||||
paths(
|
||||
routes::categories::categories,
|
||||
routes::root::root,
|
||||
|
||||
@@ -3,7 +3,7 @@ use axum::{
|
||||
Json,
|
||||
};
|
||||
use revolt_database::User;
|
||||
use revolt_result::{create_error, Result};
|
||||
use revolt_result::{create_error, Result, Error};
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
|
||||
@@ -21,10 +21,11 @@ pub struct CategoriesQueryParams {
|
||||
get,
|
||||
path = "/categories",
|
||||
tag = "GIFs",
|
||||
security(("User Token" = []), ("Bot Token" = [])),
|
||||
security(("Session-Token" = []), ("Bot-Token" = [])),
|
||||
params(CategoriesQueryParams),
|
||||
responses(
|
||||
(status = 200, description = "Categories results", body = inline(Vec<types::CategoryResponse>))
|
||||
(status = 200, description = "Categories results", body = inline(Vec<types::CategoryResponse>)),
|
||||
(status = "default", body = Error)
|
||||
)
|
||||
)]
|
||||
pub async fn categories(
|
||||
|
||||
@@ -3,7 +3,7 @@ use axum::{
|
||||
Json,
|
||||
};
|
||||
use revolt_database::User;
|
||||
use revolt_result::{create_error, Result};
|
||||
use revolt_result::{Error, Result, create_error};
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
|
||||
@@ -30,10 +30,11 @@ pub struct SearchQueryParams {
|
||||
get,
|
||||
path = "/search",
|
||||
tag = "GIFs",
|
||||
security(("User Token" = []), ("Bot Token" = [])),
|
||||
security(("Session-Token" = []), ("Bot-Token" = [])),
|
||||
params(SearchQueryParams),
|
||||
responses(
|
||||
(status = 200, description = "Search results", body = inline(types::PaginatedMediaResponse))
|
||||
(status = 200, description = "Search results", body = types::PaginatedMediaResponse),
|
||||
(status = "default", body = Error)
|
||||
)
|
||||
)]
|
||||
pub async fn search(
|
||||
|
||||
@@ -3,7 +3,7 @@ use axum::{
|
||||
Json,
|
||||
};
|
||||
use revolt_database::User;
|
||||
use revolt_result::{create_error, Result};
|
||||
use revolt_result::{create_error, Result, Error};
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
|
||||
@@ -25,10 +25,11 @@ pub struct TrendingQueryParams {
|
||||
get,
|
||||
path = "/featured",
|
||||
tag = "GIFs",
|
||||
security(("User Token" = []), ("Bot Token" = [])),
|
||||
security(("Session-Token" = []), ("Bot-Token" = [])),
|
||||
params(TrendingQueryParams),
|
||||
responses(
|
||||
(status = 200, description = "Trending results", body = inline(types::PaginatedMediaResponse))
|
||||
(status = 200, description = "Trending results", body = types::PaginatedMediaResponse),
|
||||
(status = "default", body = Error),
|
||||
)
|
||||
)]
|
||||
pub async fn trending(
|
||||
|
||||
@@ -41,9 +41,9 @@ revolt-result = { version = "0.8.9", path = "../../core/result", features = [
|
||||
revolt-files = { version = "0.8.9", path = "../../core/files" }
|
||||
|
||||
# Axum / web server
|
||||
axum = { version = "0.7.5" }
|
||||
axum-extra = { version = "0.9", features = ["typed-header"] }
|
||||
axum = { version = "0.8.6" }
|
||||
axum-extra = { version = "0.12.0", features = ["typed-header"] }
|
||||
|
||||
# OpenAPI & documentation generation
|
||||
utoipa-scalar = { version = "0.1.0", features = ["axum"] }
|
||||
utoipa = { version = "4.2.3", features = ["axum_extras", "ulid"] }
|
||||
utoipa-scalar = { version = "0.3.0", features = ["axum"] }
|
||||
utoipa = { version = "5.4.0", features = ["ulid"] }
|
||||
|
||||
@@ -80,9 +80,6 @@ async fn proxy(Query(UrlQuery { url }): Query<UrlQuery>) -> Result<impl IntoResp
|
||||
params(
|
||||
("url" = String, Query, description = "URL to fetch")
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
)
|
||||
)]
|
||||
async fn embed(
|
||||
Query(UrlQuery { url }): Query<UrlQuery>,
|
||||
|
||||
@@ -3,11 +3,8 @@ use std::net::{Ipv4Addr, SocketAddr};
|
||||
use axum::Router;
|
||||
|
||||
use tokio::net::TcpListener;
|
||||
use utoipa::{
|
||||
openapi::security::{Http, HttpAuthScheme, SecurityScheme},
|
||||
Modify, OpenApi,
|
||||
};
|
||||
use utoipa_scalar::{Scalar, Servable as ScalarServable};
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_scalar::{Scalar, Servable};
|
||||
|
||||
mod api;
|
||||
pub mod requests;
|
||||
@@ -21,7 +18,6 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
// Configure API schema
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
modifiers(&SecurityAddon),
|
||||
paths(
|
||||
api::root,
|
||||
api::proxy,
|
||||
@@ -47,22 +43,17 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
)]
|
||||
struct ApiDoc;
|
||||
|
||||
struct SecurityAddon;
|
||||
|
||||
impl Modify for SecurityAddon {
|
||||
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
||||
if let Some(components) = openapi.components.as_mut() {
|
||||
components.add_security_scheme(
|
||||
"api_key",
|
||||
SecurityScheme::Http(Http::new(HttpAuthScheme::Bearer)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure Axum and router
|
||||
let app = Router::new()
|
||||
.merge(Scalar::with_url("/scalar", ApiDoc::openapi()))
|
||||
// .route("/scalar", {
|
||||
// let html = Scalar::new(ApiDoc::openapi()).to_html();
|
||||
|
||||
// get(move || {
|
||||
// let html = html.clone();
|
||||
// async { Html(html) }
|
||||
// })
|
||||
// })
|
||||
.nest("/", api::router().await);
|
||||
|
||||
// Configure TCP listener and bind
|
||||
|
||||
Reference in New Issue
Block a user