#![cfg(feature = "actix_extras")] use fastapi::OpenApi; mod common; mod derive_params_multiple_actix { use actix_web::{web, HttpResponse, Responder}; use serde_json::json; /// Get foo by id /// /// Get foo by id long description #[fastapi::path( get, path = "/foo/{id}/{digest}", responses( (status = 200, description = "success response") ), params( ("id", description = "Foo id"), ("digest", description = "Digest of foo"), ) )] #[allow(unused)] async fn get_foo_by_id(path: web::Path<(i32, String)>) -> impl Responder { let (id, digest) = path.into_inner(); HttpResponse::Ok().json(json!({ "foo": format!("{:?}{:?}", &id, &digest) })) } } #[test] fn derive_path_parameter_multiple_with_matching_names_and_types_actix_success() { #[derive(OpenApi, Default)] #[openapi(paths(derive_params_multiple_actix::get_foo_by_id))] struct ApiDoc; let doc = serde_json::to_value(ApiDoc::openapi()).unwrap(); let parameters = doc .pointer("/paths/~1foo~1{id}~1{digest}/get/parameters") .unwrap(); common::assert_json_array_len(parameters, 2); assert_value! {parameters=> "[0].in" = r#""path""#, "Parameter in" "[0].name" = r#""id""#, "Parameter name" "[0].description" = r#""Foo id""#, "Parameter description" "[0].required" = r#"true"#, "Parameter required" "[0].deprecated" = r#"null"#, "Parameter deprecated" "[0].schema.type" = r#""integer""#, "Parameter schema type" "[0].schema.format" = r#""int32""#, "Parameter schema format" "[1].in" = r#""path""#, "Parameter in" "[1].name" = r#""digest""#, "Parameter name" "[1].description" = r#""Digest of foo""#, "Parameter description" "[1].required" = r#"true"#, "Parameter required" "[1].deprecated" = r#"null"#, "Parameter deprecated" "[1].schema.type" = r#""string""#, "Parameter schema type" "[1].schema.format" = r#"null"#, "Parameter schema format" }; } mod derive_parameters_multiple_no_matching_names_actix { use actix_web::{web, HttpResponse, Responder}; use serde_json::json; /// Get foo by id /// /// Get foo by id long description #[fastapi::path( get, path = "/foo/{id}/{digest}", responses( (status = 200, description = "success response") ), params( ("id" = i32, description = "Foo id"), ("digest" = String, description = "Digest of foo"), ) )] #[allow(unused)] async fn get_foo_by_id(info: web::Path<(i32, String)>) -> impl Responder { // is no matching names since the parameter name does not match to amount of types HttpResponse::Ok().json(json!({ "foo": format!("{:?}{:?}", &info.0, &info.1) })) } } #[test] fn derive_path_parameter_multiple_no_matching_names_actix_success() { #[derive(OpenApi, Default)] #[openapi(paths(derive_parameters_multiple_no_matching_names_actix::get_foo_by_id))] struct ApiDoc; let doc = serde_json::to_value(ApiDoc::openapi()).unwrap(); let parameters = doc .pointer("/paths/~1foo~1{id}~1{digest}/get/parameters") .unwrap(); common::assert_json_array_len(parameters, 2); assert_value! {parameters=> "[0].in" = r#""path""#, "Parameter in" "[0].name" = r#""id""#, "Parameter name" "[0].description" = r#""Foo id""#, "Parameter description" "[0].required" = r#"true"#, "Parameter required" "[0].deprecated" = r#"null"#, "Parameter deprecated" "[0].schema.type" = r#""integer""#, "Parameter schema type" "[0].schema.format" = r#""int32""#, "Parameter schema format" "[1].in" = r#""path""#, "Parameter in" "[1].name" = r#""digest""#, "Parameter name" "[1].description" = r#""Digest of foo""#, "Parameter description" "[1].required" = r#"true"#, "Parameter required" "[1].deprecated" = r#"null"#, "Parameter deprecated" "[1].schema.type" = r#""string""#, "Parameter schema type" "[1].schema.format" = r#"null"#, "Parameter schema format" }; } mod derive_params_from_method_args_actix { use actix_web::{web, HttpResponse, Responder}; use serde_json::json; #[fastapi::path( get, path = "/foo/{id}/{digest}", responses( (status = 200, description = "success response") ), )] #[allow(unused)] async fn get_foo_by_id(path: web::Path<(i32, String)>) -> impl Responder { let (id, digest) = path.into_inner(); HttpResponse::Ok().json(json!({ "foo": format!("{:?}{:?}", &id, &digest) })) } } #[test] fn derive_params_from_method_args_actix_success() { #[derive(OpenApi, Default)] #[openapi(paths(derive_params_from_method_args_actix::get_foo_by_id))] struct ApiDoc; let doc = serde_json::to_value(ApiDoc::openapi()).unwrap(); let parameters = doc .pointer("/paths/~1foo~1{id}~1{digest}/get/parameters") .unwrap(); common::assert_json_array_len(parameters, 2); assert_value! {parameters=> "[0].in" = r#""path""#, "Parameter in" "[0].name" = r#""id""#, "Parameter name" "[0].description" = r#"null"#, "Parameter description" "[0].required" = r#"true"#, "Parameter required" "[0].deprecated" = r#"null"#, "Parameter deprecated" "[0].schema.type" = r#""integer""#, "Parameter schema type" "[0].schema.format" = r#""int32""#, "Parameter schema format" "[1].in" = r#""path""#, "Parameter in" "[1].name" = r#""digest""#, "Parameter name" "[1].description" = r#"null"#, "Parameter description" "[1].required" = r#"true"#, "Parameter required" "[1].deprecated" = r#"null"#, "Parameter deprecated" "[1].schema.type" = r#""string""#, "Parameter schema type" "[1].schema.format" = r#"null"#, "Parameter schema format" }; } #[test] #[cfg(feature = "chrono")] fn derive_path_with_date_params_chrono_implicit() { mod mod_derive_path_with_date_params { use actix_web::{get, web, HttpResponse, Responder}; use chrono::{DateTime, Utc}; use serde_json::json; use time::Date; #[fastapi::path( responses( (status = 200, description = "success response") ), params( ("start_date", description = "Start date filter"), ("end_date", description = "End date filter"), ) )] #[get("/visitors/v1/{start_date}/{end_date}")] #[allow(unused)] async fn get_foo_by_date(path: web::Path<(Date, DateTime)>) -> impl Responder { let (start_date, end_date) = path.into_inner(); HttpResponse::Ok() .json(json!({ "params": &format!("{:?} {:?}", start_date, end_date) })) } } #[derive(OpenApi, Default)] #[openapi(paths(mod_derive_path_with_date_params::get_foo_by_date))] struct ApiDoc; let doc = serde_json::to_value(ApiDoc::openapi()).unwrap(); let parameters = doc .pointer("/paths/~1visitors~1v1~1{start_date}~1{end_date}/get/parameters") .unwrap(); common::assert_json_array_len(parameters, 2); assert_value! {parameters=> "[0].in" = r#""path""#, "Parameter in" "[0].name" = r#""start_date""#, "Parameter name" "[0].description" = r#""Start date filter""#, "Parameter description" "[0].required" = r#"true"#, "Parameter required" "[0].deprecated" = r#"null"#, "Parameter deprecated" "[0].schema.type" = r#""string""#, "Parameter schema type" "[0].schema.format" = r#""date""#, "Parameter schema format" "[1].in" = r#""path""#, "Parameter in" "[1].name" = r#""end_date""#, "Parameter name" "[1].description" = r#""End date filter""#, "Parameter description" "[1].required" = r#"true"#, "Parameter required" "[1].deprecated" = r#"null"#, "Parameter deprecated" "[1].schema.type" = r#""string""#, "Parameter schema type" "[1].schema.format" = r#""date-time""#, "Parameter schema format" }; } #[test] #[cfg(feature = "time")] fn derive_path_with_date_params_explicit_ignored_time() { mod mod_derive_path_with_date_params { use actix_web::{get, web, HttpResponse, Responder}; use serde_json::json; use time::Date; #[fastapi::path( responses( (status = 200, description = "success response") ), params( ("start_date", description = "Start date filter", format = Date), ("end_date", description = "End date filter", format = DateTime), ) )] #[get("/visitors/v1/{start_date}/{end_date}")] #[allow(unused)] async fn get_foo_by_date(path: web::Path<(Date, String)>) -> impl Responder { let (start_date, end_date) = path.into_inner(); HttpResponse::Ok() .json(json!({ "params": &format!("{:?} {:?}", start_date, end_date) })) } } #[derive(OpenApi, Default)] #[openapi(paths(mod_derive_path_with_date_params::get_foo_by_date))] struct ApiDoc; let doc = serde_json::to_value(ApiDoc::openapi()).unwrap(); let parameters = doc .pointer("/paths/~1visitors~1v1~1{start_date}~1{end_date}/get/parameters") .unwrap(); common::assert_json_array_len(parameters, 2); assert_value! {parameters=> "[0].in" = r#""path""#, "Parameter in" "[0].name" = r#""start_date""#, "Parameter name" "[0].description" = r#""Start date filter""#, "Parameter description" "[0].required" = r#"true"#, "Parameter required" "[0].deprecated" = r#"null"#, "Parameter deprecated" "[0].schema.type" = r#""string""#, "Parameter schema type" "[0].schema.format" = r#""date""#, "Parameter schema format" "[1].in" = r#""path""#, "Parameter in" "[1].name" = r#""end_date""#, "Parameter name" "[1].description" = r#""End date filter""#, "Parameter description" "[1].required" = r#"true"#, "Parameter required" "[1].deprecated" = r#"null"#, "Parameter deprecated" "[1].schema.type" = r#""string""#, "Parameter schema type" "[1].schema.format" = r#""date-time""#, "Parameter schema format" }; }