Skip to content

[New Generator] Rust API client generator#6092

Merged
wing328 merged 2 commits intoswagger-api:masterfrom
farcaller:rust
Jul 21, 2017
Merged

[New Generator] Rust API client generator#6092
wing328 merged 2 commits intoswagger-api:masterfrom
farcaller:rust

Conversation

@farcaller
Copy link
Copy Markdown
Contributor

PR checklist

  • Read the contribution guidelines.
  • Ran the shell script under ./bin/ to update Petstore sample so that CIs can verify the change. (For instance, only need to run ./bin/{LANG}-petstore.sh and ./bin/security/{LANG}-petstore.sh if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in .\bin\windows\.
  • Filed the PR against the correct branch: master for non-breaking changes and 3.0.0 branch for breaking (non-backward compatible) changes.

Description of the PR

Tracking PR for Rust client implementation.

The first commit adds a subset of apis requested in #5905.

@farcaller
Copy link
Copy Markdown
Contributor Author

I'll add a few comments on the specifics inline

@@ -0,0 +1,17 @@
[package]
name = "petstore-client"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these settings would be exposed as flags.

@@ -0,0 +1,44 @@
extern crate petstore_client;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a sample file, not to be part of generated api

use super::models;
use super::Error;

pub fn add_pet<C: hyper::client::Connect>(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rust naming guidelines dictate snake_case in function names

use super::Error;

pub fn add_pet<C: hyper::client::Connect>(
prefix: &str,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about what's the common pattern for api use, really. This sample client will require two things: a http (or https) prefix as a string and the hyper.rs Client (the web client) plus any arguments.

let mut req = hyper::Request::new(
hyper::Method::Post,
format!("{}/pet", prefix).parse().unwrap());
let serialized = serde_json::to_string(pet).unwrap();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no error handling for brevity of the example.

Box::new(
cli.request(req).and_then(|res| { res.body().concat2() })
.map_err(|e| Error::from(e))
.and_then(|_| futures::future::ok(()))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the api doesn't dictate the return value so nothing is returned even though the sample server returns a pet instance.

npm server choked up on {"id":1337,"category":null,"name":"barker","photoUrls":[],"tags":[],"status":null} here, http://petstore.swagger.io worked fine.


use super::models;

mod get_pet_by_id_api;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a single namespace, so modules (and files) would have to be named differently from the actual functions.

id: Option<i64>,
category: Option<super::Category>,
name: String,
#[serde(rename = "photoUrls")] photo_urls: Vec<String>,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, snake case here, and renamed fields need an annotation.

@wing328
Copy link
Copy Markdown
Contributor

wing328 commented Jul 17, 2017

@farcaller thanks for the Rust Petstore sample, I'll start the reverse engineering process tomorrow and let you know if I've any question.

@farcaller
Copy link
Copy Markdown
Contributor Author

I poked more around the go generated code and brought the example to the similar level of api. The changes, basically, are that there's an APIClient now, that incapsulates access to the API, and a dedicated pet_api.rs that's supposedly implements all the Pet apis. This extension fully builds on the previous example, though, so it would be fine if the generator produced the functional API as in original commit, and I can tackle the object API later myself when I'll have a better understanding of swagger internals.

@wing328
Copy link
Copy Markdown
Contributor

wing328 commented Jul 18, 2017

Quick question: would it be possible to group add_pet_api.rs, get_pet_by_id_api.rs, update_pet_with_form_api.rs into a single rs file (e.g. pet_api_func.rs)?

@farcaller
Copy link
Copy Markdown
Contributor Author

Absolutely. I'll update the PR

@wing328
Copy link
Copy Markdown
Contributor

wing328 commented Jul 18, 2017

@farcaller I've submitted the initial version via #6105

Please comment on the code in that PR and we'll fix the remaining issues one by one.

base64 = "*"
futures = "*"
hyper = "*"
url = "*"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind annotating which dependency version is the codegen targeting?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, as soon as I figure those myself :-) so far the generated code doesn't compile

prefix: &str,
cli: &hyper::client::Client<C>,
pet_id: i64,
) -> Box<Future<Item = models::Pet, Error = Error>> {
Copy link
Copy Markdown

@lucab lucab Jul 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Here and in other generated methods)
Would you consider returning a more complex type? The Item here is losing any additional information about the response (header, status, etc) which I've found useful in some situations (e.g. token authenticated endpoints redirecting to token provider). For reference, reqwest does this with a richer Response struct + trait.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For other generators (e.g. PHP, Ruby), there's a corresponding "WithHttpInfo" method (e.g. getPetByIdWithHttpInfo) to return a list with the response (if any), HTTP status code and HTTP headers.

Not sure if Rust supports returning a list. If not, we will need to create an ApiResponse object with response, status and headers as properties.

For Rust, we can follow similar approach by creating a corresponding WithHttpInfo method or we can default the method (e.g. getPetById) to return the response together with status code and headers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can return response object along with the parsed body. Let's focus on making the current implementation compileable and then we can improve.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also worth sharing other API clients usually come with a corresponding "Async" method (e.g. addPetAsync) for async function call. Not sure how that should be done in Rust but worth thinking ahead with this future requirement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this code is async-only. I don't think that it makes sense to have a matching sync version.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. Good to know. One less thing to consider then.

@wing328
Copy link
Copy Markdown
Contributor

wing328 commented Jul 21, 2017

Merging this (Rust Petstore sample) into master first similar to what we've done for PowerShell and other generators that follow similar approach so as to give credits back to the contributor.

For further discussion on the Rust generator, please continue in #6105, which is work-in-progress.

@wing328 wing328 merged commit 1f133e8 into swagger-api:master Jul 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants