[New Generator] Rust API client generator (#6092)

* Added rust client example

* Added a proper apiclient / configuration based example
This commit is contained in:
Vladimir Pouzanov 2017-07-21 14:58:31 +01:00 committed by wing328
parent faa62ee40c
commit 1f133e8ecd
15 changed files with 339 additions and 0 deletions

View File

@ -0,0 +1,3 @@
/target/
**/*.rs.bk
Cargo.lock

View File

@ -0,0 +1,17 @@
[package]
name = "petstore-client"
version = "0.1.0"
authors = ["Vladimir Pouzanov <farcaller@gmail.com>"]
[dependencies]
serde = "*"
serde_derive = "*"
serde_yaml = "*"
serde_json = "*"
base64 = "*"
futures = "*"
hyper = "*"
url = "*"
[dev-dependencies]
tokio-core = "*"

View File

@ -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");
}

View File

@ -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<C: hyper::client::Connect>(
prefix: &str,
cli: &hyper::client::Client<C>,
pet: &models::Pet,
) -> Box<Future<Item = (), Error = Error>> {
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(()))
)
}

View File

@ -0,0 +1,26 @@
use std::rc::Rc;
use hyper;
use super::configuration::Configuration;
use super::pet_api;
pub struct APIClient<C: hyper::client::Connect> {
configuration: Rc<Configuration<C>>,
pet_api: Box<pet_api::PetAPI>,
}
impl<C: hyper::client::Connect> APIClient<C> {
pub fn new(configuration: Configuration<C>) -> APIClient<C> {
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()
}
}

View File

@ -0,0 +1,15 @@
use hyper;
pub struct Configuration<C: hyper::client::Connect> {
pub base_path: String,
pub client: hyper::client::Client<C>,
}
impl<C: hyper::client::Connect> Configuration<C> {
pub fn new(client: hyper::client::Client<C>) -> Configuration<C> {
Configuration {
base_path: "http://petstore.swagger.io:80/v2".to_owned(),
client: client,
}
}
}

View File

@ -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<C: hyper::client::Connect>(
prefix: &str,
cli: &hyper::client::Client<C>,
pet_id: i64,
) -> Box<Future<Item = models::Pet, Error = Error>> {
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<models::Pet, _> = serde_json::from_slice(&body);
parsed.map_err(|e| Error::from(e))
}).map_err(|e| Error::from(e))
)
}

View File

@ -0,0 +1,37 @@
use hyper;
use serde_json;
#[derive(Debug)]
pub enum Error {
Hyper(hyper::Error),
Serde(serde_json::Error),
}
impl From<hyper::Error> for Error {
fn from(e: hyper::Error) -> Self {
return Error::Hyper(e)
}
}
impl From<serde_json::Error> 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;

View File

@ -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<Future<Item = (), Error = Error>>;
}
pub struct PetAPIImpl<C: hyper::client::Connect> {
configuration: Rc<configuration::Configuration<C>>,
}
impl<C: hyper::client::Connect> PetAPIImpl<C> {
pub fn new(configuration: Rc<configuration::Configuration<C>>) -> PetAPIImpl<C> {
PetAPIImpl {
configuration: configuration,
}
}
}
impl<C: hyper::client::Connect>PetAPI for PetAPIImpl<C> {
fn add_pet(&self, pet: &models::Pet) -> Box<Future<Item = (), Error = Error>> {
let configuration: &configuration::Configuration<C> = 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(()))
)
}
}

View File

@ -0,0 +1,31 @@
use hyper;
use futures::{Future, Stream};
use url;
use futures;
use super::Error;
pub fn update_pet_with_form<C: hyper::client::Connect>(
prefix: &str,
cli: &hyper::client::Client<C>,
pet_id: i64,
name: &str,
status: &str,
) -> Box<Future<Item = (), Error = Error>> {
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(()))
)
}

View File

@ -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;

View File

@ -0,0 +1,8 @@
/// Pet catehgry
///
/// A category for a pet
#[derive(Debug, Serialize, Deserialize)]
pub struct Category {
id: Option<i64>,
name: Option<String>,
}

View File

@ -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;

View File

@ -0,0 +1,34 @@
/// a Pet
///
/// A pet for sale in the pet store
#[derive(Debug, Serialize, Deserialize)]
pub struct Pet {
id: Option<i64>,
category: Option<super::Category>,
name: String,
#[serde(rename = "photoUrls")] photo_urls: Vec<String>,
tags: Vec<super::Tag>,
status: Option<String>,
}
impl Pet {
pub fn new(name: String, photo_urls: Vec<String>) -> 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
}
}

View File

@ -0,0 +1,8 @@
/// Pet Tag
///
/// A tag for a pet
#[derive(Debug, Serialize, Deserialize)]
pub struct Tag {
id: Option<i64>,
name: Option<String>,
}