From 1f133e8ecd5a3bcbe4424f1bbcda98b61e3b1c30 Mon Sep 17 00:00:00 2001 From: Vladimir Pouzanov Date: Fri, 21 Jul 2017 14:58:31 +0100 Subject: [PATCH] [New Generator] Rust API client generator (#6092) * Added rust client example * Added a proper apiclient / configuration based example --- samples/client/petstore/rust/.gitignore | 3 ++ samples/client/petstore/rust/Cargo.toml | 17 +++++++ .../client/petstore/rust/examples/client.rs | 48 +++++++++++++++++++ .../petstore/rust/src/apis/add_pet_api.rs | 27 +++++++++++ .../client/petstore/rust/src/apis/client.rs | 26 ++++++++++ .../petstore/rust/src/apis/configuration.rs | 15 ++++++ .../rust/src/apis/get_pet_by_id_api.rs | 23 +++++++++ samples/client/petstore/rust/src/apis/mod.rs | 37 ++++++++++++++ .../client/petstore/rust/src/apis/pet_api.rs | 44 +++++++++++++++++ .../rust/src/apis/update_pet_with_form_api.rs | 31 ++++++++++++ samples/client/petstore/rust/src/lib.rs | 10 ++++ .../petstore/rust/src/models/category.rs | 8 ++++ .../client/petstore/rust/src/models/mod.rs | 8 ++++ .../client/petstore/rust/src/models/pet.rs | 34 +++++++++++++ .../client/petstore/rust/src/models/tag.rs | 8 ++++ 15 files changed, 339 insertions(+) create mode 100644 samples/client/petstore/rust/.gitignore create mode 100644 samples/client/petstore/rust/Cargo.toml create mode 100644 samples/client/petstore/rust/examples/client.rs create mode 100644 samples/client/petstore/rust/src/apis/add_pet_api.rs create mode 100644 samples/client/petstore/rust/src/apis/client.rs create mode 100644 samples/client/petstore/rust/src/apis/configuration.rs create mode 100644 samples/client/petstore/rust/src/apis/get_pet_by_id_api.rs create mode 100644 samples/client/petstore/rust/src/apis/mod.rs create mode 100644 samples/client/petstore/rust/src/apis/pet_api.rs create mode 100644 samples/client/petstore/rust/src/apis/update_pet_with_form_api.rs create mode 100644 samples/client/petstore/rust/src/lib.rs create mode 100644 samples/client/petstore/rust/src/models/category.rs create mode 100644 samples/client/petstore/rust/src/models/mod.rs create mode 100644 samples/client/petstore/rust/src/models/pet.rs create mode 100644 samples/client/petstore/rust/src/models/tag.rs diff --git a/samples/client/petstore/rust/.gitignore b/samples/client/petstore/rust/.gitignore new file mode 100644 index 00000000000..6aa106405a4 --- /dev/null +++ b/samples/client/petstore/rust/.gitignore @@ -0,0 +1,3 @@ +/target/ +**/*.rs.bk +Cargo.lock diff --git a/samples/client/petstore/rust/Cargo.toml b/samples/client/petstore/rust/Cargo.toml new file mode 100644 index 00000000000..8c2c024a747 --- /dev/null +++ b/samples/client/petstore/rust/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "petstore-client" +version = "0.1.0" +authors = ["Vladimir Pouzanov "] + +[dependencies] +serde = "*" +serde_derive = "*" +serde_yaml = "*" +serde_json = "*" +base64 = "*" +futures = "*" +hyper = "*" +url = "*" + +[dev-dependencies] +tokio-core = "*" diff --git a/samples/client/petstore/rust/examples/client.rs b/samples/client/petstore/rust/examples/client.rs new file mode 100644 index 00000000000..f690146421f --- /dev/null +++ b/samples/client/petstore/rust/examples/client.rs @@ -0,0 +1,48 @@ +extern crate petstore_client; +extern crate hyper; +extern crate tokio_core; +extern crate futures; + +use hyper::Client; +use hyper::client::HttpConnector; +use tokio_core::reactor::Core; +use futures::{Future}; + +fn main() { + let mut core = Core::new().expect("failed to init core"); + let handle = core.handle(); + + let http_connector = HttpConnector::new(4, &handle); + + let client = Client::configure().connector(http_connector).build(&handle); + let api = "http://petstore.swagger.io:80/v2"; + + let new_pet = petstore_client::models::Pet::new("barker".to_owned(), vec![]).with_id(1337); + + let apicli = petstore_client::apis::client::APIClient::new( + petstore_client::apis::configuration::Configuration::new( + Client::configure().connector(HttpConnector::new(4, &handle)).build(&handle))); + + let work = apicli.pet_api().add_pet(&new_pet) + // petstore_client::apis::add_pet(api, &client, &new_pet) + .and_then(|_| { + petstore_client::apis::update_pet_with_form( + api, + &client, + 1337, + "barko", + "escaped") + }) + .and_then(|_| { + petstore_client::apis::get_pet_by_id( + api, + &client, + 1337) + }) + .and_then(|pet| { + println!("pet: {:?}", pet); + futures::future::ok(()) + }); + + core.run(work).expect("failed to run core"); +} diff --git a/samples/client/petstore/rust/src/apis/add_pet_api.rs b/samples/client/petstore/rust/src/apis/add_pet_api.rs new file mode 100644 index 00000000000..2d43880ce2d --- /dev/null +++ b/samples/client/petstore/rust/src/apis/add_pet_api.rs @@ -0,0 +1,27 @@ +use hyper; +use serde_json; +use futures::{Future, Stream}; +use futures; + +use super::models; +use super::Error; + +pub fn add_pet( + prefix: &str, + cli: &hyper::client::Client, + pet: &models::Pet, + ) -> Box> { + let mut req = hyper::Request::new( + hyper::Method::Post, + format!("{}/pet", prefix).parse().unwrap()); + let serialized = serde_json::to_string(pet).unwrap(); + req.headers_mut().set(hyper::header::ContentType::json()); + req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); + req.set_body(serialized); + + Box::new( + cli.request(req).and_then(|res| { res.body().concat2() }) + .map_err(|e| Error::from(e)) + .and_then(|_| futures::future::ok(())) + ) +} diff --git a/samples/client/petstore/rust/src/apis/client.rs b/samples/client/petstore/rust/src/apis/client.rs new file mode 100644 index 00000000000..606f0eba578 --- /dev/null +++ b/samples/client/petstore/rust/src/apis/client.rs @@ -0,0 +1,26 @@ +use std::rc::Rc; + +use hyper; +use super::configuration::Configuration; +use super::pet_api; + +pub struct APIClient { + configuration: Rc>, + + pet_api: Box, +} + +impl APIClient { + pub fn new(configuration: Configuration) -> APIClient { + let rc = Rc::new(configuration); + + APIClient { + configuration: rc.clone(), + pet_api: Box::new(pet_api::PetAPIImpl::new(rc.clone())), + } + } + + pub fn pet_api(&self) -> &pet_api::PetAPI { + self.pet_api.as_ref() + } +} diff --git a/samples/client/petstore/rust/src/apis/configuration.rs b/samples/client/petstore/rust/src/apis/configuration.rs new file mode 100644 index 00000000000..25b4d645f3e --- /dev/null +++ b/samples/client/petstore/rust/src/apis/configuration.rs @@ -0,0 +1,15 @@ +use hyper; + +pub struct Configuration { + pub base_path: String, + pub client: hyper::client::Client, +} + +impl Configuration { + pub fn new(client: hyper::client::Client) -> Configuration { + Configuration { + base_path: "http://petstore.swagger.io:80/v2".to_owned(), + client: client, + } + } +} diff --git a/samples/client/petstore/rust/src/apis/get_pet_by_id_api.rs b/samples/client/petstore/rust/src/apis/get_pet_by_id_api.rs new file mode 100644 index 00000000000..74ae95dc7da --- /dev/null +++ b/samples/client/petstore/rust/src/apis/get_pet_by_id_api.rs @@ -0,0 +1,23 @@ +use hyper; +use serde_json; +use futures::{Future, Stream}; + +use super::models; +use super::Error; + +pub fn get_pet_by_id( + prefix: &str, + cli: &hyper::client::Client, + pet_id: i64, + ) -> Box> { + Box::new( + cli.get(format!("{}/pet/{}", prefix, pet_id).parse().unwrap()) + + .and_then(|res| { res.body().concat2() }).map_err(|e| Error::from(e)) + + .and_then(|body| { + let parsed: Result = serde_json::from_slice(&body); + parsed.map_err(|e| Error::from(e)) + }).map_err(|e| Error::from(e)) + ) +} diff --git a/samples/client/petstore/rust/src/apis/mod.rs b/samples/client/petstore/rust/src/apis/mod.rs new file mode 100644 index 00000000000..b1cba2957ef --- /dev/null +++ b/samples/client/petstore/rust/src/apis/mod.rs @@ -0,0 +1,37 @@ +use hyper; +use serde_json; + +#[derive(Debug)] +pub enum Error { + Hyper(hyper::Error), + Serde(serde_json::Error), +} + +impl From for Error { + fn from(e: hyper::Error) -> Self { + return Error::Hyper(e) + } +} + +impl From for Error { + fn from(e: serde_json::Error) -> Self { + return Error::Serde(e) + } +} + +use super::models; + +mod get_pet_by_id_api; +pub use self::get_pet_by_id_api::get_pet_by_id; + +mod update_pet_with_form_api; +pub use self::update_pet_with_form_api::update_pet_with_form; + +mod add_pet_api; +pub use self::add_pet_api::add_pet; + +pub mod configuration; +pub mod client; + +mod pet_api; +pub use self::pet_api::PetAPI; diff --git a/samples/client/petstore/rust/src/apis/pet_api.rs b/samples/client/petstore/rust/src/apis/pet_api.rs new file mode 100644 index 00000000000..d413b95664b --- /dev/null +++ b/samples/client/petstore/rust/src/apis/pet_api.rs @@ -0,0 +1,44 @@ +use std::rc::Rc; +use std::borrow::Borrow; + +use hyper; +use serde_json; +use futures; +use futures::{Future, Stream}; + +use super::{Error, configuration, models}; + +pub trait PetAPI { + fn add_pet(&self, pet: &models::Pet) -> Box>; +} + +pub struct PetAPIImpl { + configuration: Rc>, +} + +impl PetAPIImpl { + pub fn new(configuration: Rc>) -> PetAPIImpl { + PetAPIImpl { + configuration: configuration, + } + } +} + +implPetAPI for PetAPIImpl { + fn add_pet(&self, pet: &models::Pet) -> Box> { + let configuration: &configuration::Configuration = self.configuration.borrow(); + let mut req = hyper::Request::new( + hyper::Method::Post, + format!("{}/pet", configuration.base_path).parse().unwrap()); + let serialized = serde_json::to_string(pet).unwrap(); + req.headers_mut().set(hyper::header::ContentType::json()); + req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); + req.set_body(serialized); + + Box::new( + configuration.client.request(req).and_then(|res| { res.body().concat2() }) + .map_err(|e| Error::from(e)) + .and_then(|_| futures::future::ok(())) + ) + } +} diff --git a/samples/client/petstore/rust/src/apis/update_pet_with_form_api.rs b/samples/client/petstore/rust/src/apis/update_pet_with_form_api.rs new file mode 100644 index 00000000000..a721d362179 --- /dev/null +++ b/samples/client/petstore/rust/src/apis/update_pet_with_form_api.rs @@ -0,0 +1,31 @@ +use hyper; +use futures::{Future, Stream}; +use url; +use futures; + +use super::Error; + +pub fn update_pet_with_form( + prefix: &str, + cli: &hyper::client::Client, + pet_id: i64, + name: &str, + status: &str, + ) -> Box> { + let mut req = hyper::Request::new( + hyper::Method::Post, + format!("{}/pet/{}", prefix, pet_id).parse().unwrap()); + let body = url::form_urlencoded::Serializer::new(String::new()) + .append_pair("name", name) + .append_pair("status", status) + .finish(); + req.headers_mut().set(hyper::header::ContentType::form_url_encoded()); + req.headers_mut().set(hyper::header::ContentLength(body.len() as u64)); + req.set_body(body); + + Box::new( + cli.request(req).and_then(|res| { res.body().concat2() }) + .map_err(|e| Error::from(e)) + .and_then(|_| futures::future::ok(())) + ) +} diff --git a/samples/client/petstore/rust/src/lib.rs b/samples/client/petstore/rust/src/lib.rs new file mode 100644 index 00000000000..2ad195c6fb1 --- /dev/null +++ b/samples/client/petstore/rust/src/lib.rs @@ -0,0 +1,10 @@ +#[macro_use] +extern crate serde_derive; + +extern crate hyper; +extern crate serde_json; +extern crate futures; +extern crate url; + +pub mod apis; +pub mod models; diff --git a/samples/client/petstore/rust/src/models/category.rs b/samples/client/petstore/rust/src/models/category.rs new file mode 100644 index 00000000000..c69e9d147bb --- /dev/null +++ b/samples/client/petstore/rust/src/models/category.rs @@ -0,0 +1,8 @@ +/// Pet catehgry +/// +/// A category for a pet +#[derive(Debug, Serialize, Deserialize)] +pub struct Category { + id: Option, + name: Option, +} diff --git a/samples/client/petstore/rust/src/models/mod.rs b/samples/client/petstore/rust/src/models/mod.rs new file mode 100644 index 00000000000..4b8e81e42d6 --- /dev/null +++ b/samples/client/petstore/rust/src/models/mod.rs @@ -0,0 +1,8 @@ +mod pet; +pub use self::pet::Pet; + +mod category; +pub use self::category::Category; + +mod tag; +pub use self::tag::Tag; diff --git a/samples/client/petstore/rust/src/models/pet.rs b/samples/client/petstore/rust/src/models/pet.rs new file mode 100644 index 00000000000..c812a0dbccb --- /dev/null +++ b/samples/client/petstore/rust/src/models/pet.rs @@ -0,0 +1,34 @@ +/// a Pet +/// +/// A pet for sale in the pet store +#[derive(Debug, Serialize, Deserialize)] +pub struct Pet { + id: Option, + category: Option, + name: String, + #[serde(rename = "photoUrls")] photo_urls: Vec, + tags: Vec, + status: Option, +} + +impl Pet { + pub fn new(name: String, photo_urls: Vec) -> Pet { + Pet { + id: None, + category: None, + name: name, + photo_urls: photo_urls, + tags: Vec::new(), + status: None, + } + } + + pub fn set_id(&mut self, id: i64) { + self.id = Some(id); + } + + pub fn with_id(mut self, id: i64) -> Pet { + self.id = Some(id); + self + } +} diff --git a/samples/client/petstore/rust/src/models/tag.rs b/samples/client/petstore/rust/src/models/tag.rs new file mode 100644 index 00000000000..2ebb742c8f7 --- /dev/null +++ b/samples/client/petstore/rust/src/models/tag.rs @@ -0,0 +1,8 @@ +/// Pet Tag +/// +/// A tag for a pet +#[derive(Debug, Serialize, Deserialize)] +pub struct Tag { + id: Option, + name: Option, +}