From 0d27078571e1105b23e358c71a54ba580c5eaf37 Mon Sep 17 00:00:00 2001
From: Steven <asongala@163.com>
Date: Thu, 26 Aug 2021 20:54:22 +0800
Subject: [PATCH] Init `open-api` with an example. (#290)

---
 Cargo.lock         | 133 +++++++++++++++++++++++++++++++++++++++++++++
 Cargo.toml         |   5 ++
 src/bin/openapi.rs |  32 +++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 src/bin/openapi.rs

diff --git a/Cargo.lock b/Cargo.lock
index 4c8e7452..89dde0c9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -709,6 +709,7 @@ dependencies = [
  "nix",
  "num_enum",
  "orchestra",
+ "paperclip",
  "qstring",
  "rand 0.8.3",
  "serde 1.0.124",
@@ -735,6 +736,12 @@ version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
 
+[[package]]
+name = "dtoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
+
 [[package]]
 name = "either"
 version = "1.6.1"
@@ -1262,6 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
 dependencies = [
  "scopeguard",
+ "serde 1.0.124",
 ]
 
 [[package]]
@@ -1565,6 +1573,77 @@ dependencies = [
  "tonic-build",
 ]
 
+[[package]]
+name = "paperclip"
+version = "0.5.0"
+source = "git+https://github.com/fluidex/paperclip.git#374e30b0bbef538f536f896999313c03f995a69a"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "once_cell",
+ "paperclip-actix",
+ "paperclip-core",
+ "paperclip-macros",
+ "parking_lot",
+ "semver",
+ "serde 1.0.124",
+ "serde_derive",
+ "serde_json",
+ "serde_yaml",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "paperclip-actix"
+version = "0.3.0"
+source = "git+https://github.com/fluidex/paperclip.git#374e30b0bbef538f536f896999313c03f995a69a"
+dependencies = [
+ "actix-service",
+ "actix-web",
+ "futures",
+ "once_cell",
+ "paperclip-core",
+ "paperclip-macros",
+ "parking_lot",
+ "serde_json",
+]
+
+[[package]]
+name = "paperclip-core"
+version = "0.3.0"
+source = "git+https://github.com/fluidex/paperclip.git#374e30b0bbef538f536f896999313c03f995a69a"
+dependencies = [
+ "actix-web",
+ "mime",
+ "once_cell",
+ "paperclip-macros",
+ "parking_lot",
+ "pin-project",
+ "regex",
+ "serde 1.0.124",
+ "serde_json",
+ "serde_yaml",
+ "thiserror",
+]
+
+[[package]]
+name = "paperclip-macros"
+version = "0.4.0"
+source = "git+https://github.com/fluidex/paperclip.git#374e30b0bbef538f536f896999313c03f995a69a"
+dependencies = [
+ "heck",
+ "http",
+ "lazy_static",
+ "mime",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "strum",
+ "strum_macros",
+ "syn",
+]
+
 [[package]]
 name = "parking_lot"
 version = "0.11.1"
@@ -1729,6 +1808,30 @@ dependencies = [
  "toml",
 ]
 
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
 [[package]]
 name = "proc-macro-hack"
 version = "0.5.19"
@@ -2169,6 +2272,18 @@ dependencies = [
  "serde 1.0.124",
 ]
 
+[[package]]
+name = "serde_yaml"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6375dbd828ed6964c3748e4ef6d18e7a175d408ffe184bca01698d0c73f915a9"
+dependencies = [
+ "dtoa",
+ "indexmap",
+ "serde 1.0.124",
+ "yaml-rust",
+]
+
 [[package]]
 name = "sha-1"
 version = "0.9.4"
@@ -2433,6 +2548,24 @@ dependencies = [
  "unicode-normalization",
 ]
 
+[[package]]
+name = "strum"
+version = "0.19.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b89a286a7e3b5720b9a477b23253bc50debac207c8d21505f8e70b36792f11b5"
+
+[[package]]
+name = "strum_macros"
+version = "0.19.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e61bb0be289045cb80bfce000512e32d09f8337e54c186725da381377ad1f8d5"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "subtle"
 version = "2.4.0"
diff --git a/Cargo.toml b/Cargo.toml
index 798519c8..020508aa 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,7 @@ log = "0.4.14"
 nix = "0.20.0"
 num_enum = "0.5.1"
 orchestra = { git = "https://github.com/fluidex/orchestra.git", branch = "master", features = [ "exchange" ] }
+paperclip = { git = "https://github.com/fluidex/paperclip.git", features = ["actix"] }
 qstring = "0.7.2"
 rand = "0.8.3"
 serde = { version = "1.0.124", features = [ "derive" ] }
@@ -42,6 +43,10 @@ tracing-appender = "0.1"
 tracing-subscriber = "0.2"
 ttl_cache = "0.5.1"
 
+[[bin]]
+name = "openapi"
+path = "src/bin/openapi.rs"
+
 [[bin]]
 name = "restapi"
 path = "src/bin/restapi.rs"
diff --git a/src/bin/openapi.rs b/src/bin/openapi.rs
new file mode 100644
index 00000000..7e7dad69
--- /dev/null
+++ b/src/bin/openapi.rs
@@ -0,0 +1,32 @@
+use actix_web::{App, HttpServer};
+use paperclip::actix::{
+    api_v2_operation,
+    web::{self, Json},
+    Apiv2Schema, OpenApiExt,
+};
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Apiv2Schema)]
+struct Pet {
+    name: String,
+    id: Option<i64>,
+}
+
+#[api_v2_operation]
+async fn echo_pet(body: Json<Pet>) -> Result<Json<Pet>, actix_web::Error> {
+    Ok(body)
+}
+
+#[actix_web::main]
+async fn main() -> std::io::Result<()> {
+    HttpServer::new(|| {
+        App::new()
+            .wrap_api()
+            .service(web::resource("/pets").route(web::post().to(echo_pet)))
+            .with_json_spec_at("/api/spec")
+            .build()
+    })
+    .bind("0.0.0.0:50054")?
+    .run()
+    .await
+}