#![allow(dead_code)] use fastapi::{ openapi::{ self, security::{HttpAuthScheme, HttpBuilder, SecurityScheme}, server::{ServerBuilder, ServerVariableBuilder}, }, Modify, OpenApi, ToSchema, }; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, ToSchema)] #[schema(example = json!({"name": "bob the cat", "id": 1}))] struct Pet { id: u64, name: String, age: Option, } // #[derive(ToSchema)] // struct Status { // status: StatusType, // } // #[derive(ToSchema)] // enum StatusType { // Ok, // NotOk, // } // #[derive(ToSchema)] // enum Random { // Response { id: String }, // PetResponse(Pet), // Ids(Vec), // UnitValue, // } // #[derive(Serialize, Deserialize, ToSchema)] // struct Simple { // greeting: &'static str, // cow: Cow<'static, str>, // } mod pet_api { use super::*; const ID: &str = "get_pet"; /// Get pet by id /// /// Get pet from database by pet database id #[fastapi::path( get, operation_id = ID, path = "/pets/{id}", responses( (status = 200, description = "Pet found successfully", body = Pet), (status = 404, description = "Pet was not found") ), params( ("id" = u64, Path, description = "Pet database id to get Pet for"), ), security( (), ("my_auth" = ["read:items", "edit:items"]), ("token_jwt" = []) ) )] #[allow(unused)] async fn get_pet_by_id(pet_id: u64) -> Pet { Pet { id: pet_id, age: None, name: "lightning".to_string(), } } } #[derive(Default, OpenApi)] #[openapi( paths(pet_api::get_pet_by_id), components(schemas(Pet, C, C)), modifiers(&Foo), security( (), ("my_auth" = ["read:items", "edit:items"]), ("token_jwt" = []) ) )] struct ApiDoc; macro_rules! build_foo { ($typ: ident, $d: ty, $r: ty) => { #[derive(Debug, Serialize, ToSchema)] struct $typ { data: $d, resources: $r, } }; } #[derive(Deserialize, Serialize, ToSchema)] struct A { a: String, } #[derive(Deserialize, Serialize, ToSchema)] struct B { b: i64, } #[derive(Deserialize, Serialize, ToSchema)] struct C { field_1: R, field_2: T, } impl Modify for Foo { fn modify(&self, openapi: &mut openapi::OpenApi) { if let Some(schema) = openapi.components.as_mut() { schema.add_security_scheme( "token_jwt", SecurityScheme::Http( HttpBuilder::new() .scheme(HttpAuthScheme::Bearer) .bearer_format("JWT") .build(), ), ) } openapi.servers = Some(vec![ServerBuilder::new() .url("/api/bar/{username}") .description(Some("this is description of the server")) .parameter( "username", ServerVariableBuilder::new() .default_value("the_user") .description(Some("this is user")), ) .build()]); } } #[derive(Debug, Serialize, ToSchema)] struct Foo; #[derive(Debug, Serialize, ToSchema)] struct FooResources; #[test] #[ignore = "this is just a test bed to run macros"] fn derive_openapi() { fastapi::openapi::OpenApi::new( fastapi::openapi::Info::new("my application", "0.1.0"), fastapi::openapi::Paths::new(), ); println!("{}", ApiDoc::openapi().to_pretty_json().unwrap()); build_foo!(GetFooBody, Foo, FooResources); }