[Rust Server] Frunk - LabelledGeneric - support (#3552)

Derive the LabelledGeneric trait on Swagger models.  This allows
conversion between structurally similar types by using
https://docs.rs/frunk/0.2.2/frunk/#transmogrifying.

Exit if example fails to run
This commit is contained in:
Richard Whitehouse 2019-08-17 11:03:38 +01:00 committed by GitHub
parent aa4ead2a6d
commit 44fda895d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 669 additions and 519 deletions

View File

@ -38,4 +38,8 @@ for spec_path in modules/openapi-generator/src/test/resources/*/rust-server/* ;
$@"
java $JAVA_OPTS -jar $executable $args
if [ $? -ne 0 ]; then
exit $?
fi
done

View File

@ -615,10 +615,6 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
}
for (CodegenParameter param : op.headerParams) {
// If a header uses UUIDs, we need to import the UUID package.
if (param.dataType.equals(uuidType)) {
additionalProperties.put("apiUsesUuid", true);
}
processParam(param, op);
// Give header params a name in camel case. CodegenParameters don't have a nameInCamelCase property.
@ -925,7 +921,15 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
String modelName = entry.getKey();
CodegenModel model = entry.getValue();
if (uuidType.equals(model.dataType)) {
additionalProperties.put("apiUsesUuid", true);
}
for (CodegenProperty prop : model.vars) {
if (prop.dataType.equals(uuidType)) {
additionalProperties.put("apiUsesUuid", true);
}
String xmlName = modelXmlNames.get(prop.dataType);
if (xmlName != null) {
prop.vendorExtensions.put("itemXmlName", xmlName);
@ -1132,6 +1136,11 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
private void processParam(CodegenParameter param, CodegenOperation op) {
String example = null;
// If a parameter uses UUIDs, we need to import the UUID package.
if (param.dataType.equals(uuidType)) {
additionalProperties.put("apiUsesUuid", true);
}
if (param.isString) {
param.vendorExtensions.put("formatString", "\\\"{}\\\"");
example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()";

View File

@ -9,42 +9,69 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_json", {{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}} {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
server = ["serde_json", {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
client = [{{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Required by example server.
#
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "2"
# Not required by example server.
#
lazy_static = "0.2"
log = "0.3.0"
mime = "0.2.6"
multipart = {version = "0.13.3"}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
multipart = "0.13.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
{{#apiUsesUuid}}
uuid = {version = "0.5", features = ["serde", "v4"]}
{{/apiUsesUuid}}
{{#usesXml}}
# TODO: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"}
{{/usesXml}}
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
serde_json = {version = "1.0", optional = true}
serde_urlencoded = {version = "0.5.1", optional = true}
tokio-core = {version = "0.1.6", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
{{#usesUrlEncodedForm}}serde_urlencoded = {version = "0.5.1", optional = true}{{/usesUrlEncodedForm}}
# Server-specific
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
url = {version = "1.5", optional = true}
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
# ToDo: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
{{#usesXml}}serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true}{{/usesXml}}
# Other optional crates
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }
frunk-enum-derive = { version = "0.2.0", optional = true }
frunk-enum-core = { version = "0.2.0", optional = true }
[dev-dependencies]
clap = "2.25"
error-chain = "0.12"
{{^apiUsesUuid}}
uuid = {version = "0.5", features = ["serde", "v4"]}
{{/apiUsesUuid}}
[[example]]
name = "client"
required-features = ["client"]
[[example]]
name = "server"
required-features = ["server"]

View File

@ -5,22 +5,20 @@
{{/appDescription}}
## Overview
This client/server was generated by the [openapi-generator]
(https://openapi-generator.tech) project.
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
-
(https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
server, you can easily generate a server stub.
To see how to make this your own, look here:
[README]((https://openapi-generator.tech))
- API version: {{{appVersion}}}
{{^hideGenerationTimestamp}}
- Build date: {{{generatedDate}}}
{{/hideGenerationTimestamp}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}
{{^hideGenerationTimestamp}}- Build date: {{{generatedDate}}}{{/hideGenerationTimestamp}}
{{#infoUrl}}For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}){{/infoUrl}}
This autogenerated project defines an API crate `{{{packageName}}}` which contains:
* An `Api` trait defining the API in Rust.
@ -29,15 +27,17 @@ This autogenerated project defines an API crate `{{{packageName}}}` which contai
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
It also contains an example server and client which make use of `{{{packageName}}}`:
* The example server starts up a web server using the `{{{packageName}}}` router,
and supplies a trivial implementation of `Api` which returns failure for every operation.
* The example client provides a CLI which lets you invoke any single operation on the
`{{{packageName}}}` client by passing appropriate arguments on the command line.
* The example server starts up a web server using the `{{{packageName}}}`
router, and supplies a trivial implementation of `Api` which returns failure
for every operation.
* The example client provides a CLI which lets you invoke
any single operation on the `{{{packageName}}}` client by passing appropriate
arguments on the command line.
You can use the example server and client as a basis for your own code.
See below for [more detail on implementing a server](#writing-a-server).
## Examples
Run examples with:
@ -52,14 +52,14 @@ To pass in arguments to the examples, put them after `--`, for example:
cargo run --example client -- --help
```
### Running the server
### Running the example server
To run the server, follow these simple steps:
```
cargo run --example server
```
### Running a client
### Running the example client
To run a client, follow one of the following simple steps:
```{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
@ -73,43 +73,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam
cargo run --example server -- --https
```
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
`CN=localhost`.
This will use the keys/certificates from the examples directory. Note that the
server chain is signed with `CN=localhost`.
## Using the generated library
## Writing a server
The generated library has a few optional features that can be activated through Cargo.
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
* `server`
* This defaults to enabled and creates the basic skeleton of a server implementation based on hyper
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* Set up a new Rust project, e.g., with `cargo init --bin`.
* Insert `{{{packageName}}}` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "{{{packageName}}}" ]`.
* Add `{{{packageName}}} = {version = "{{{appVersion}}}", path = "{{{packageName}}}"}` under `[dependencies]` in the root `Cargo.toml`.
* Copy the `[dependencies]` and `[dev-dependencies]` from `{{{packageName}}}/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
* Remove `"optional = true"` from each of these lines if present.
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
```
cp {{{packageName}}}/examples/server.rs src/main.rs
cp {{{packageName}}}/examples/server_lib/mod.rs src/lib.rs
cp {{{packageName}}}/examples/server_lib/server.rs src/server.rs
```
Now
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
* Run `cargo build` to check it builds.
* Run `cargo fmt` to reformat the code.
* Commit the result before making any further changes (lest format changes get confused with your own updates).
Now replace the implementations in `src/server.rs` with your own code as required.
## Updating your server to track API changes
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
Alternatively, implement the now-missing methods based on the compiler's error messages.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@ -12,10 +12,10 @@ extern crate serde_urlencoded;
{{#apiUsesMultipart}}
extern crate multipart;
{{/apiUsesMultipart}}
{{#apiUsesUuid}}
use uuid;
extern crate uuid;
{{/apiUsesUuid}}
use hyper;
use hyper::header::{Headers, ContentType};
use hyper::Uri;

View File

@ -7,9 +7,9 @@ extern crate futures;
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate uuid;
extern crate clap;
extern crate tokio_core;
extern crate uuid;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};

View File

@ -20,7 +20,9 @@ extern crate futures;
extern crate chrono;
#[macro_use]
extern crate error_chain;
{{#apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}}
{{#apiUsesUuid}}
extern crate uuid;
{{/apiUsesUuid}}
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};

View File

@ -6,9 +6,11 @@ use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}}
use swagger;
use swagger::{Has, XSpanIdString};
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}
use {{{externCrateName}}}::{Api, ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

View File

@ -1,40 +1,53 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
{{#apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}}
{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}}
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate mime;
#[macro_use]
extern crate serde_derive;
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
// Crates for conversion support
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_derives;
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_enum_derive;
#[cfg(feature = "conversion")]
extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}}
extern crate futures;
extern crate chrono;
extern crate swagger;
{{#apiUsesUuid}}
extern crate uuid;
{{/apiUsesUuid}}
use futures::Stream;
use std::io::Error;
#[allow(unused_imports)]
use std::collections::HashMap;
pub use futures::Future;
#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;
#[deprecated(note = "Import swagger-rs directly")]
pub use swagger::{ApiError, ContextWrapper};
#[deprecated(note = "Import futures directly")]
pub use futures::Future;
pub const BASE_PATH: &'static str = "{{{basePathWithoutHost}}}";
pub const API_VERSION: &'static str = "{{{appVersion}}}";

View File

@ -1,6 +1,5 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;
{{#usesXml}}
use serde_xml_rs;
@ -16,7 +15,9 @@ use std::collections::HashMap;
use models;
use swagger;
use std::string::ParseError;
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}
{{#models}}{{#model}}
{{#description}}/// {{{description}}}
@ -25,7 +26,8 @@ use std::string::ParseError;
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)]{{#xmlName}}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))]{{#xmlName}}
#[serde(rename = "{{{xmlName}}}")]{{/xmlName}}
pub enum {{{classname}}} { {{#allowableValues}}{{#enumVars}}
#[serde(rename = {{{value}}})]
@ -50,6 +52,7 @@ impl ::std::str::FromStr for {{{classname}}} {
}
}
{{/isEnum}}{{^isEnum}}{{#dataType}}{{! newtype}}#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
{{#xmlName}}#[serde(rename = "{{{xmlName}}}")]{{/xmlName}}
pub struct {{{classname}}}({{{dataType}}});
@ -97,6 +100,7 @@ where
}
{{/itemXmlName}}{{/vendorExtensions}}{{! vec}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct {{{classname}}}({{#vendorExtensions}}{{#itemXmlName}}#[serde(serialize_with = "wrap_in_{{{itemXmlName}}}")]{{/itemXmlName}}{{/vendorExtensions}}Vec<{{{arrayModelType}}}>);
impl ::std::convert::From<Vec<{{{arrayModelType}}}>> for {{{classname}}} {
@ -157,7 +161,8 @@ impl ::std::ops::DerefMut for {{{classname}}} {
}
}
{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]{{#xmlName}}
{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]{{#xmlName}}
#[serde(rename = "{{{xmlName}}}")]{{/xmlName}}
pub struct {{{classname}}} {
{{#vars}}{{#description}} /// {{{description}}}

View File

@ -8,7 +8,7 @@ extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
{{^apiUsesUuid}}
{{#apiUsesUuid}}
extern crate uuid;
{{/apiUsesUuid}}
{{#apiUsesMultipart}}
@ -32,9 +32,6 @@ use serde_json;
{{#usesXml}}
use serde_xml_rs;
{{/usesXml}}
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};

View File

@ -7,42 +7,59 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
server = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Required by example server.
#
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "2"
# Not required by example server.
#
lazy_static = "0.2"
log = "0.3.0"
mime = "0.2.6"
multipart = {version = "0.13.3"}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
multipart = "0.13.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
serde_json = {version = "1.0", optional = true}
serde_urlencoded = {version = "0.5.1", optional = true}
tokio-core = {version = "0.1.6", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
url = {version = "1.5", optional = true}
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
# ToDo: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
# Other optional crates
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }
frunk-enum-derive = { version = "0.2.0", optional = true }
frunk-enum-core = { version = "0.2.0", optional = true }
[dev-dependencies]
clap = "2.25"
error-chain = "0.12"
uuid = {version = "0.5", features = ["serde", "v4"]}
[[example]]
name = "client"
required-features = ["client"]
[[example]]
name = "server"
required-features = ["server"]

View File

@ -3,10 +3,11 @@
API under test
## Overview
This client/server was generated by the [openapi-generator]
(https://openapi-generator.tech) project.
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
-
(https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
server, you can easily generate a server stub.
To see how to make this your own, look here:
@ -14,6 +15,9 @@ To see how to make this your own, look here:
- API version: 1.0.7
This autogenerated project defines an API crate `multipart-v3` which contains:
* An `Api` trait defining the API in Rust.
* Data types representing the underlying data model.
@ -21,15 +25,17 @@ This autogenerated project defines an API crate `multipart-v3` which contains:
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
It also contains an example server and client which make use of `multipart-v3`:
* The example server starts up a web server using the `multipart-v3` router,
and supplies a trivial implementation of `Api` which returns failure for every operation.
* The example client provides a CLI which lets you invoke any single operation on the
`multipart-v3` client by passing appropriate arguments on the command line.
* The example server starts up a web server using the `multipart-v3`
router, and supplies a trivial implementation of `Api` which returns failure
for every operation.
* The example client provides a CLI which lets you invoke
any single operation on the `multipart-v3` client by passing appropriate
arguments on the command line.
You can use the example server and client as a basis for your own code.
See below for [more detail on implementing a server](#writing-a-server).
## Examples
Run examples with:
@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example:
cargo run --example client -- --help
```
### Running the server
### Running the example server
To run the server, follow these simple steps:
```
cargo run --example server
```
### Running a client
### Running the example client
To run a client, follow one of the following simple steps:
```
@ -65,43 +71,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam
cargo run --example server -- --https
```
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
`CN=localhost`.
This will use the keys/certificates from the examples directory. Note that the
server chain is signed with `CN=localhost`.
## Using the generated library
## Writing a server
The generated library has a few optional features that can be activated through Cargo.
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
* `server`
* This defaults to enabled and creates the basic skeleton of a server implementation based on hyper
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* Set up a new Rust project, e.g., with `cargo init --bin`.
* Insert `multipart-v3` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "multipart-v3" ]`.
* Add `multipart-v3 = {version = "1.0.7", path = "multipart-v3"}` under `[dependencies]` in the root `Cargo.toml`.
* Copy the `[dependencies]` and `[dev-dependencies]` from `multipart-v3/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
* Remove `"optional = true"` from each of these lines if present.
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
```
cp multipart-v3/examples/server.rs src/main.rs
cp multipart-v3/examples/server_lib/mod.rs src/lib.rs
cp multipart-v3/examples/server_lib/server.rs src/server.rs
```
Now
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
* Run `cargo build` to check it builds.
* Run `cargo fmt` to reformat the code.
* Commit the result before making any further changes (lest format changes get confused with your own updates).
Now replace the implementations in `src/server.rs` with your own code as required.
## Updating your server to track API changes
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
Alternatively, implement the now-missing methods based on the compiler's error messages.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@ -7,9 +7,9 @@ extern crate futures;
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate uuid;
extern crate clap;
extern crate tokio_core;
extern crate uuid;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};

View File

@ -21,7 +21,6 @@ extern crate chrono;
#[macro_use]
extern crate error_chain;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;

View File

@ -6,7 +6,6 @@ use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use swagger;
use swagger::{Has, XSpanIdString};

View File

@ -1,40 +1,50 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate mime;
#[macro_use]
extern crate serde_derive;
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
// Crates for conversion support
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_derives;
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_enum_derive;
#[cfg(feature = "conversion")]
extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate chrono;
extern crate swagger;
use futures::Stream;
use std::io::Error;
#[allow(unused_imports)]
use std::collections::HashMap;
pub use futures::Future;
#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;
#[deprecated(note = "Import swagger-rs directly")]
pub use swagger::{ApiError, ContextWrapper};
#[deprecated(note = "Import futures directly")]
pub use futures::Future;
pub const BASE_PATH: &'static str = "";
pub const API_VERSION: &'static str = "1.0.7";

View File

@ -1,6 +1,5 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;
use serde::ser::Serializer;
@ -10,8 +9,8 @@ use swagger;
use std::string::ParseError;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct MultipartRequest {
#[serde(rename = "string_field")]
pub string_field: String,
@ -42,6 +41,7 @@ impl MultipartRequest {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct MultipartRequestObjectField {
#[serde(rename = "field_a")]
pub field_a: String,

View File

@ -8,7 +8,6 @@ extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
extern crate uuid;
extern crate multipart;
use std::sync::Arc;

View File

@ -7,42 +7,62 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Required by example server.
#
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "2"
# Not required by example server.
#
lazy_static = "0.2"
log = "0.3.0"
mime = "0.2.6"
multipart = {version = "0.13.3"}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
multipart = "0.13.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
uuid = {version = "0.5", features = ["serde", "v4"]}
# TODO: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"}
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
serde_json = {version = "1.0", optional = true}
serde_urlencoded = {version = "0.5.1", optional = true}
tokio-core = {version = "0.1.6", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
url = {version = "1.5", optional = true}
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
# ToDo: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true}
# Other optional crates
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }
frunk-enum-derive = { version = "0.2.0", optional = true }
frunk-enum-core = { version = "0.2.0", optional = true }
[dev-dependencies]
clap = "2.25"
error-chain = "0.12"
[[example]]
name = "client"
required-features = ["client"]
[[example]]
name = "server"
required-features = ["server"]

View File

@ -3,10 +3,11 @@
API under test
## Overview
This client/server was generated by the [openapi-generator]
(https://openapi-generator.tech) project.
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
-
(https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
server, you can easily generate a server stub.
To see how to make this your own, look here:
@ -14,6 +15,9 @@ To see how to make this your own, look here:
- API version: 1.0.7
This autogenerated project defines an API crate `openapi-v3` which contains:
* An `Api` trait defining the API in Rust.
* Data types representing the underlying data model.
@ -21,15 +25,17 @@ This autogenerated project defines an API crate `openapi-v3` which contains:
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
It also contains an example server and client which make use of `openapi-v3`:
* The example server starts up a web server using the `openapi-v3` router,
and supplies a trivial implementation of `Api` which returns failure for every operation.
* The example client provides a CLI which lets you invoke any single operation on the
`openapi-v3` client by passing appropriate arguments on the command line.
* The example server starts up a web server using the `openapi-v3`
router, and supplies a trivial implementation of `Api` which returns failure
for every operation.
* The example client provides a CLI which lets you invoke
any single operation on the `openapi-v3` client by passing appropriate
arguments on the command line.
You can use the example server and client as a basis for your own code.
See below for [more detail on implementing a server](#writing-a-server).
## Examples
Run examples with:
@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example:
cargo run --example client -- --help
```
### Running the server
### Running the example server
To run the server, follow these simple steps:
```
cargo run --example server
```
### Running a client
### Running the example client
To run a client, follow one of the following simple steps:
```
@ -71,43 +77,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam
cargo run --example server -- --https
```
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
`CN=localhost`.
This will use the keys/certificates from the examples directory. Note that the
server chain is signed with `CN=localhost`.
## Using the generated library
## Writing a server
The generated library has a few optional features that can be activated through Cargo.
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
* `server`
* This defaults to enabled and creates the basic skeleton of a server implementation based on hyper
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* Set up a new Rust project, e.g., with `cargo init --bin`.
* Insert `openapi-v3` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "openapi-v3" ]`.
* Add `openapi-v3 = {version = "1.0.7", path = "openapi-v3"}` under `[dependencies]` in the root `Cargo.toml`.
* Copy the `[dependencies]` and `[dev-dependencies]` from `openapi-v3/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
* Remove `"optional = true"` from each of these lines if present.
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
```
cp openapi-v3/examples/server.rs src/main.rs
cp openapi-v3/examples/server_lib/mod.rs src/lib.rs
cp openapi-v3/examples/server_lib/server.rs src/server.rs
```
Now
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
* Run `cargo build` to check it builds.
* Run `cargo fmt` to reformat the code.
* Commit the result before making any further changes (lest format changes get confused with your own updates).
Now replace the implementations in `src/server.rs` with your own code as required.
## Updating your server to track API changes
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
Alternatively, implement the now-missing methods based on the compiler's error messages.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@ -7,9 +7,9 @@ extern crate futures;
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate uuid;
extern crate clap;
extern crate tokio_core;
extern crate uuid;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};

View File

@ -20,7 +20,7 @@ extern crate futures;
extern crate chrono;
#[macro_use]
extern crate error_chain;
extern crate uuid;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};

View File

@ -6,9 +6,9 @@ use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use swagger;
use swagger::{Has, XSpanIdString};
use uuid;
use openapi_v3::{Api, ApiError,
RequiredOctetStreamPutResponse,

View File

@ -6,6 +6,7 @@ extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate url;
extern crate uuid;
use hyper;
use hyper::header::{Headers, ContentType};

View File

@ -1,40 +1,51 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate mime;
#[macro_use]
extern crate serde_derive;
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
// Crates for conversion support
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_derives;
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_enum_derive;
#[cfg(feature = "conversion")]
extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate futures;
extern crate chrono;
extern crate swagger;
extern crate uuid;
use futures::Stream;
use std::io::Error;
#[allow(unused_imports)]
use std::collections::HashMap;
pub use futures::Future;
#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;
#[deprecated(note = "Import swagger-rs directly")]
pub use swagger::{ApiError, ContextWrapper};
#[deprecated(note = "Import futures directly")]
pub use futures::Future;
pub const BASE_PATH: &'static str = "";
pub const API_VERSION: &'static str = "1.0.7";

View File

@ -1,6 +1,5 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;
use serde_xml_rs;
use serde::ser::Serializer;
@ -9,7 +8,7 @@ use std::collections::{HashMap, BTreeMap};
use models;
use swagger;
use std::string::ParseError;
use uuid;
// Utility function for wrapping list elements when serializing xml
@ -22,6 +21,7 @@ where
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct AnotherXmlArray(#[serde(serialize_with = "wrap_in_snake_another_xml_inner")]Vec<String>);
impl ::std::convert::From<Vec<String>> for AnotherXmlArray {
@ -93,6 +93,7 @@ impl AnotherXmlArray {
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "snake_another_xml_inner")]
pub struct AnotherXmlInner(String);
@ -140,6 +141,7 @@ impl AnotherXmlInner {
/// An XML object
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "snake_another_xml_object")]
pub struct AnotherXmlObject {
#[serde(rename = "inner_string")]
@ -176,6 +178,7 @@ impl AnotherXmlObject {
/// An XML object
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "camelDuplicateXmlObject")]
pub struct DuplicateXmlObject {
#[serde(rename = "inner_string")]
@ -217,6 +220,7 @@ impl DuplicateXmlObject {
/// Test a model containing a UUID
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct UuidObject(uuid::Uuid);
@ -266,6 +270,7 @@ where
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct XmlArray(#[serde(serialize_with = "wrap_in_camelXmlInner")]Vec<String>);
impl ::std::convert::From<Vec<String>> for XmlArray {
@ -337,6 +342,7 @@ impl XmlArray {
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "camelXmlInner")]
pub struct XmlInner(String);
@ -384,6 +390,7 @@ impl XmlInner {
/// An XML object
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "camelXmlObject")]
pub struct XmlObject {
#[serde(rename = "innerString")]

View File

@ -7,42 +7,59 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
server = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Required by example server.
#
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "2"
# Not required by example server.
#
lazy_static = "0.2"
log = "0.3.0"
mime = "0.2.6"
multipart = {version = "0.13.3"}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
multipart = "0.13.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
serde_json = {version = "1.0", optional = true}
serde_urlencoded = {version = "0.5.1", optional = true}
tokio-core = {version = "0.1.6", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
url = {version = "1.5", optional = true}
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
# ToDo: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
# Other optional crates
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }
frunk-enum-derive = { version = "0.2.0", optional = true }
frunk-enum-core = { version = "0.2.0", optional = true }
[dev-dependencies]
clap = "2.25"
error-chain = "0.12"
uuid = {version = "0.5", features = ["serde", "v4"]}
[[example]]
name = "client"
required-features = ["client"]
[[example]]
name = "server"
required-features = ["server"]

View File

@ -3,10 +3,11 @@
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
## Overview
This client/server was generated by the [openapi-generator]
(https://openapi-generator.tech) project.
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
-
(https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
server, you can easily generate a server stub.
To see how to make this your own, look here:
@ -14,6 +15,9 @@ To see how to make this your own, look here:
- API version: 0.0.1
This autogenerated project defines an API crate `ops-v3` which contains:
* An `Api` trait defining the API in Rust.
* Data types representing the underlying data model.
@ -21,15 +25,17 @@ This autogenerated project defines an API crate `ops-v3` which contains:
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
It also contains an example server and client which make use of `ops-v3`:
* The example server starts up a web server using the `ops-v3` router,
and supplies a trivial implementation of `Api` which returns failure for every operation.
* The example client provides a CLI which lets you invoke any single operation on the
`ops-v3` client by passing appropriate arguments on the command line.
* The example server starts up a web server using the `ops-v3`
router, and supplies a trivial implementation of `Api` which returns failure
for every operation.
* The example client provides a CLI which lets you invoke
any single operation on the `ops-v3` client by passing appropriate
arguments on the command line.
You can use the example server and client as a basis for your own code.
See below for [more detail on implementing a server](#writing-a-server).
## Examples
Run examples with:
@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example:
cargo run --example client -- --help
```
### Running the server
### Running the example server
To run the server, follow these simple steps:
```
cargo run --example server
```
### Running a client
### Running the example client
To run a client, follow one of the following simple steps:
```
@ -101,43 +107,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam
cargo run --example server -- --https
```
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
`CN=localhost`.
This will use the keys/certificates from the examples directory. Note that the
server chain is signed with `CN=localhost`.
## Using the generated library
## Writing a server
The generated library has a few optional features that can be activated through Cargo.
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
* `server`
* This defaults to enabled and creates the basic skeleton of a server implementation based on hyper
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* Set up a new Rust project, e.g., with `cargo init --bin`.
* Insert `ops-v3` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "ops-v3" ]`.
* Add `ops-v3 = {version = "0.0.1", path = "ops-v3"}` under `[dependencies]` in the root `Cargo.toml`.
* Copy the `[dependencies]` and `[dev-dependencies]` from `ops-v3/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
* Remove `"optional = true"` from each of these lines if present.
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
```
cp ops-v3/examples/server.rs src/main.rs
cp ops-v3/examples/server_lib/mod.rs src/lib.rs
cp ops-v3/examples/server_lib/server.rs src/server.rs
```
Now
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
* Run `cargo build` to check it builds.
* Run `cargo fmt` to reformat the code.
* Commit the result before making any further changes (lest format changes get confused with your own updates).
Now replace the implementations in `src/server.rs` with your own code as required.
## Updating your server to track API changes
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
Alternatively, implement the now-missing methods based on the compiler's error messages.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@ -7,9 +7,9 @@ extern crate futures;
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate uuid;
extern crate clap;
extern crate tokio_core;
extern crate uuid;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};

View File

@ -21,7 +21,6 @@ extern crate chrono;
#[macro_use]
extern crate error_chain;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;

View File

@ -6,7 +6,6 @@ use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use swagger;
use swagger::{Has, XSpanIdString};

View File

@ -1,40 +1,50 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate mime;
#[macro_use]
extern crate serde_derive;
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
// Crates for conversion support
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_derives;
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_enum_derive;
#[cfg(feature = "conversion")]
extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate chrono;
extern crate swagger;
use futures::Stream;
use std::io::Error;
#[allow(unused_imports)]
use std::collections::HashMap;
pub use futures::Future;
#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;
#[deprecated(note = "Import swagger-rs directly")]
pub use swagger::{ApiError, ContextWrapper};
#[deprecated(note = "Import futures directly")]
pub use futures::Future;
pub const BASE_PATH: &'static str = "";
pub const API_VERSION: &'static str = "0.0.1";

View File

@ -1,6 +1,5 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;
use serde::ser::Serializer;
@ -9,4 +8,3 @@ use models;
use swagger;
use std::string::ParseError;

View File

@ -8,7 +8,6 @@ extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
extern crate uuid;
use std::sync::Arc;
use std::marker::PhantomData;

View File

@ -7,42 +7,62 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_json", "serde_urlencoded", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
client = ["serde_urlencoded", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Required by example server.
#
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "2"
# Not required by example server.
#
lazy_static = "0.2"
log = "0.3.0"
mime = "0.2.6"
multipart = {version = "0.13.3"}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
multipart = "0.13.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
uuid = {version = "0.5", features = ["serde", "v4"]}
# TODO: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"}
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
serde_json = {version = "1.0", optional = true}
serde_urlencoded = {version = "0.5.1", optional = true}
tokio-core = {version = "0.1.6", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
serde_urlencoded = {version = "0.5.1", optional = true}
# Server-specific
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
url = {version = "1.5", optional = true}
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
# ToDo: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true}
# Other optional crates
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }
frunk-enum-derive = { version = "0.2.0", optional = true }
frunk-enum-core = { version = "0.2.0", optional = true }
[dev-dependencies]
clap = "2.25"
error-chain = "0.12"
[[example]]
name = "client"
required-features = ["client"]
[[example]]
name = "server"
required-features = ["server"]

View File

@ -3,10 +3,11 @@
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\
## Overview
This client/server was generated by the [openapi-generator]
(https://openapi-generator.tech) project.
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
-
(https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
server, you can easily generate a server stub.
To see how to make this your own, look here:
@ -14,6 +15,9 @@ To see how to make this your own, look here:
- API version: 1.0.0
This autogenerated project defines an API crate `petstore-with-fake-endpoints-models-for-testing` which contains:
* An `Api` trait defining the API in Rust.
* Data types representing the underlying data model.
@ -21,15 +25,17 @@ This autogenerated project defines an API crate `petstore-with-fake-endpoints-mo
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
It also contains an example server and client which make use of `petstore-with-fake-endpoints-models-for-testing`:
* The example server starts up a web server using the `petstore-with-fake-endpoints-models-for-testing` router,
and supplies a trivial implementation of `Api` which returns failure for every operation.
* The example client provides a CLI which lets you invoke any single operation on the
`petstore-with-fake-endpoints-models-for-testing` client by passing appropriate arguments on the command line.
* The example server starts up a web server using the `petstore-with-fake-endpoints-models-for-testing`
router, and supplies a trivial implementation of `Api` which returns failure
for every operation.
* The example client provides a CLI which lets you invoke
any single operation on the `petstore-with-fake-endpoints-models-for-testing` client by passing appropriate
arguments on the command line.
You can use the example server and client as a basis for your own code.
See below for [more detail on implementing a server](#writing-a-server).
## Examples
Run examples with:
@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example:
cargo run --example client -- --help
```
### Running the server
### Running the example server
To run the server, follow these simple steps:
```
cargo run --example server
```
### Running a client
### Running the example client
To run a client, follow one of the following simple steps:
```
@ -96,43 +102,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam
cargo run --example server -- --https
```
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
`CN=localhost`.
This will use the keys/certificates from the examples directory. Note that the
server chain is signed with `CN=localhost`.
## Using the generated library
## Writing a server
The generated library has a few optional features that can be activated through Cargo.
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
* `server`
* This defaults to enabled and creates the basic skeleton of a server implementation based on hyper
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* Set up a new Rust project, e.g., with `cargo init --bin`.
* Insert `petstore-with-fake-endpoints-models-for-testing` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "petstore-with-fake-endpoints-models-for-testing" ]`.
* Add `petstore-with-fake-endpoints-models-for-testing = {version = "1.0.0", path = "petstore-with-fake-endpoints-models-for-testing"}` under `[dependencies]` in the root `Cargo.toml`.
* Copy the `[dependencies]` and `[dev-dependencies]` from `petstore-with-fake-endpoints-models-for-testing/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
* Remove `"optional = true"` from each of these lines if present.
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
```
cp petstore-with-fake-endpoints-models-for-testing/examples/server.rs src/main.rs
cp petstore-with-fake-endpoints-models-for-testing/examples/server_lib/mod.rs src/lib.rs
cp petstore-with-fake-endpoints-models-for-testing/examples/server_lib/server.rs src/server.rs
```
Now
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
* Run `cargo build` to check it builds.
* Run `cargo fmt` to reformat the code.
* Commit the result before making any further changes (lest format changes get confused with your own updates).
Now replace the implementations in `src/server.rs` with your own code as required.
## Updating your server to track API changes
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
Alternatively, implement the now-missing methods based on the compiler's error messages.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@ -7,9 +7,9 @@ extern crate futures;
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate uuid;
extern crate clap;
extern crate tokio_core;
extern crate uuid;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};

View File

@ -20,7 +20,7 @@ extern crate futures;
extern crate chrono;
#[macro_use]
extern crate error_chain;
extern crate uuid;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};

View File

@ -6,9 +6,9 @@ use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use swagger;
use swagger::{Has, XSpanIdString};
use uuid;
use petstore_with_fake_endpoints_models_for_testing::{Api, ApiError,
TestSpecialTagsResponse,

View File

@ -8,6 +8,7 @@ extern crate chrono;
extern crate url;
extern crate serde_urlencoded;
extern crate multipart;
extern crate uuid;
use hyper;
use hyper::header::{Headers, ContentType};

View File

@ -1,40 +1,51 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate mime;
#[macro_use]
extern crate serde_derive;
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
// Crates for conversion support
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_derives;
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_enum_derive;
#[cfg(feature = "conversion")]
extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate futures;
extern crate chrono;
extern crate swagger;
extern crate uuid;
use futures::Stream;
use std::io::Error;
#[allow(unused_imports)]
use std::collections::HashMap;
pub use futures::Future;
#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;
#[deprecated(note = "Import swagger-rs directly")]
pub use swagger::{ApiError, ContextWrapper};
#[deprecated(note = "Import futures directly")]
pub use futures::Future;
pub const BASE_PATH: &'static str = "/v2";
pub const API_VERSION: &'static str = "1.0.0";

View File

@ -1,6 +1,5 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;
use serde_xml_rs;
use serde::ser::Serializer;
@ -9,10 +8,11 @@ use std::collections::{HashMap, BTreeMap};
use models;
use swagger;
use std::string::ParseError;
use uuid;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct AdditionalPropertiesClass {
#[serde(rename = "map_property")]
#[serde(skip_serializing_if="Option::is_none")]
@ -43,6 +43,7 @@ impl AdditionalPropertiesClass {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct Animal {
#[serde(rename = "className")]
pub class_name: String,
@ -72,6 +73,7 @@ impl Animal {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct AnimalFarm(Vec<Animal>);
impl ::std::convert::From<Vec<Animal>> for AnimalFarm {
@ -143,6 +145,7 @@ impl AnimalFarm {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ApiResponse {
#[serde(rename = "code")]
#[serde(skip_serializing_if="Option::is_none")]
@ -178,6 +181,7 @@ impl ApiResponse {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ArrayOfArrayOfNumberOnly {
#[serde(rename = "ArrayArrayNumber")]
#[serde(skip_serializing_if="Option::is_none")]
@ -203,6 +207,7 @@ impl ArrayOfArrayOfNumberOnly {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ArrayOfNumberOnly {
#[serde(rename = "ArrayNumber")]
#[serde(skip_serializing_if="Option::is_none")]
@ -228,6 +233,7 @@ impl ArrayOfNumberOnly {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ArrayTest {
#[serde(rename = "array_of_string")]
#[serde(skip_serializing_if="Option::is_none")]
@ -269,6 +275,7 @@ impl ArrayTest {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct Capitalization {
#[serde(rename = "smallCamel")]
#[serde(skip_serializing_if="Option::is_none")]
@ -320,6 +327,7 @@ impl Capitalization {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct Cat {
#[serde(rename = "className")]
pub class_name: String,
@ -354,6 +362,7 @@ impl Cat {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct CatAllOf {
#[serde(rename = "declawed")]
#[serde(skip_serializing_if="Option::is_none")]
@ -379,6 +388,7 @@ impl CatAllOf {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Category")]
pub struct Category {
#[serde(rename = "id")]
@ -411,6 +421,7 @@ impl Category {
/// Model for testing model with \"_class\" property
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ClassModel {
#[serde(rename = "_class")]
#[serde(skip_serializing_if="Option::is_none")]
@ -436,6 +447,7 @@ impl ClassModel {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct Client {
#[serde(rename = "client")]
#[serde(skip_serializing_if="Option::is_none")]
@ -461,6 +473,7 @@ impl Client {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct Dog {
#[serde(rename = "className")]
pub class_name: String,
@ -495,6 +508,7 @@ impl Dog {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct DogAllOf {
#[serde(rename = "breed")]
#[serde(skip_serializing_if="Option::is_none")]
@ -520,6 +534,7 @@ impl DogAllOf {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct EnumArrays {
// Note: inline enums are not fully supported by openapi-generator
#[serde(rename = "just_symbol")]
@ -562,7 +577,8 @@ impl EnumArrays {
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))]
pub enum EnumClass {
#[serde(rename = "_abc")]
_ABC,
@ -604,6 +620,7 @@ impl EnumClass {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct EnumTest {
// Note: inline enums are not fully supported by openapi-generator
#[serde(rename = "enum_string")]
@ -652,6 +669,7 @@ impl EnumTest {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct FormatTest {
#[serde(rename = "integer")]
#[serde(skip_serializing_if="Option::is_none")]
@ -733,6 +751,7 @@ impl FormatTest {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct HasOnlyReadOnly {
#[serde(rename = "bar")]
#[serde(skip_serializing_if="Option::is_none")]
@ -763,6 +782,7 @@ impl HasOnlyReadOnly {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct List {
#[serde(rename = "123-list")]
#[serde(skip_serializing_if="Option::is_none")]
@ -788,6 +808,7 @@ impl List {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct MapTest {
#[serde(rename = "map_map_of_string")]
#[serde(skip_serializing_if="Option::is_none")]
@ -825,6 +846,7 @@ impl MapTest {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct MixedPropertiesAndAdditionalPropertiesClass {
#[serde(rename = "uuid")]
#[serde(skip_serializing_if="Option::is_none")]
@ -861,6 +883,7 @@ impl MixedPropertiesAndAdditionalPropertiesClass {
/// Model for testing model name starting with number
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Name")]
pub struct Model200Response {
#[serde(rename = "name")]
@ -893,6 +916,7 @@ impl Model200Response {
/// Model for testing reserved words
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Return")]
pub struct ModelReturn {
#[serde(rename = "return")]
@ -920,6 +944,7 @@ impl ModelReturn {
/// Model for testing model name same as property name
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Name")]
pub struct Name {
#[serde(rename = "name")]
@ -960,6 +985,7 @@ impl Name {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct NumberOnly {
#[serde(rename = "JustNumber")]
#[serde(skip_serializing_if="Option::is_none")]
@ -985,6 +1011,7 @@ impl NumberOnly {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Order")]
pub struct Order {
#[serde(rename = "id")]
@ -1038,6 +1065,7 @@ impl Order {
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct OuterBoolean(bool);
@ -1078,6 +1106,7 @@ impl OuterBoolean {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct OuterComposite {
#[serde(rename = "my_number")]
#[serde(skip_serializing_if="Option::is_none")]
@ -1117,7 +1146,8 @@ impl OuterComposite {
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))]
pub enum OuterEnum {
#[serde(rename = "placed")]
PLACED,
@ -1159,6 +1189,7 @@ impl OuterEnum {
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct OuterNumber(f64);
@ -1199,6 +1230,7 @@ impl OuterNumber {
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct OuterString(String);
@ -1245,6 +1277,7 @@ impl OuterString {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Pet")]
pub struct Pet {
#[serde(rename = "id")]
@ -1296,6 +1329,7 @@ impl Pet {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ReadOnlyFirst {
#[serde(rename = "bar")]
#[serde(skip_serializing_if="Option::is_none")]
@ -1326,6 +1360,7 @@ impl ReadOnlyFirst {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "$special[model.name]")]
pub struct SpecialModelName {
#[serde(rename = "$special[property.name]")]
@ -1352,6 +1387,7 @@ impl SpecialModelName {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "Tag")]
pub struct Tag {
#[serde(rename = "id")]
@ -1383,6 +1419,7 @@ impl Tag {
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
#[serde(rename = "User")]
pub struct User {
#[serde(rename = "id")]

View File

@ -7,42 +7,59 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"]
server = ["serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Required by example server.
#
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "2"
# Not required by example server.
#
lazy_static = "0.2"
log = "0.3.0"
mime = "0.2.6"
multipart = {version = "0.13.3"}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
multipart = "0.13.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
serde_json = {version = "1.0", optional = true}
serde_urlencoded = {version = "0.5.1", optional = true}
tokio-core = {version = "0.1.6", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
url = {version = "1.5", optional = true}
uuid = {version = "0.5", optional = true, features = ["serde", "v4"]}
# ToDo: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
# Other optional crates
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }
frunk-enum-derive = { version = "0.2.0", optional = true }
frunk-enum-core = { version = "0.2.0", optional = true }
[dev-dependencies]
clap = "2.25"
error-chain = "0.12"
uuid = {version = "0.5", features = ["serde", "v4"]}
[[example]]
name = "client"
required-features = ["client"]
[[example]]
name = "server"
required-features = ["server"]

View File

@ -3,10 +3,11 @@
This spec is for testing rust-server-specific things
## Overview
This client/server was generated by the [openapi-generator]
(https://openapi-generator.tech) project.
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
-
(https://openapi-generator.tech) project. By using the
[OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote
server, you can easily generate a server stub.
To see how to make this your own, look here:
@ -14,6 +15,9 @@ To see how to make this your own, look here:
- API version: 2.3.4
This autogenerated project defines an API crate `rust-server-test` which contains:
* An `Api` trait defining the API in Rust.
* Data types representing the underlying data model.
@ -21,15 +25,17 @@ This autogenerated project defines an API crate `rust-server-test` which contain
* A router which accepts HTTP requests and invokes the appropriate `Api` method for each operation.
It also contains an example server and client which make use of `rust-server-test`:
* The example server starts up a web server using the `rust-server-test` router,
and supplies a trivial implementation of `Api` which returns failure for every operation.
* The example client provides a CLI which lets you invoke any single operation on the
`rust-server-test` client by passing appropriate arguments on the command line.
* The example server starts up a web server using the `rust-server-test`
router, and supplies a trivial implementation of `Api` which returns failure
for every operation.
* The example client provides a CLI which lets you invoke
any single operation on the `rust-server-test` client by passing appropriate
arguments on the command line.
You can use the example server and client as a basis for your own code.
See below for [more detail on implementing a server](#writing-a-server).
## Examples
Run examples with:
@ -44,14 +50,14 @@ To pass in arguments to the examples, put them after `--`, for example:
cargo run --example client -- --help
```
### Running the server
### Running the example server
To run the server, follow these simple steps:
```
cargo run --example server
```
### Running a client
### Running the example client
To run a client, follow one of the following simple steps:
```
@ -69,43 +75,23 @@ The examples can be run in HTTPS mode by passing in the flag `--https`, for exam
cargo run --example server -- --https
```
This will use the keys/certificates from the examples directory. Note that the server chain is signed with
`CN=localhost`.
This will use the keys/certificates from the examples directory. Note that the
server chain is signed with `CN=localhost`.
## Using the generated library
## Writing a server
The generated library has a few optional features that can be activated through Cargo.
The server example is designed to form the basis for implementing your own server. Simply follow these steps.
* `server`
* This defaults to enabled and creates the basic skeleton of a server implementation based on hyper
* To create the server stack you'll need to provide an implementation of the API trait to provide the server function.
* `client`
* This defaults to enabled and creates the basic skeleton of a client implementation based on hyper
* The constructed client implements the API trait by making remote API call.
* `conversions`
* This defaults to disabled and creates extra derives on models to allow "transmogrification" between objects of structurally similar types.
* Set up a new Rust project, e.g., with `cargo init --bin`.
* Insert `rust-server-test` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "rust-server-test" ]`.
* Add `rust-server-test = {version = "2.3.4", path = "rust-server-test"}` under `[dependencies]` in the root `Cargo.toml`.
* Copy the `[dependencies]` and `[dev-dependencies]` from `rust-server-test/Cargo.toml` into the root `Cargo.toml`'s `[dependencies]` section.
* Copy all of the `[dev-dependencies]`, but only the `[dependencies]` that are required by the example server. These should be clearly indicated by comments.
* Remove `"optional = true"` from each of these lines if present.
Each autogenerated API will contain an implementation stub and main entry point, which should be copied into your project the first time:
```
cp rust-server-test/examples/server.rs src/main.rs
cp rust-server-test/examples/server_lib/mod.rs src/lib.rs
cp rust-server-test/examples/server_lib/server.rs src/server.rs
```
Now
* From `src/main.rs`, remove the `mod server_lib;` line, and uncomment and fill in the `extern crate` line with the name of this server crate.
* Move the block of imports "required by the service library" from `src/main.rs` to `src/lib.rs` and uncomment.
* Change the `let server = server::Server {};` line to `let server = SERVICE_NAME::server().unwrap();` where `SERVICE_NAME` is the name of the server crate.
* Run `cargo build` to check it builds.
* Run `cargo fmt` to reformat the code.
* Commit the result before making any further changes (lest format changes get confused with your own updates).
Now replace the implementations in `src/server.rs` with your own code as required.
## Updating your server to track API changes
Later, if the API changes, you can copy new sections from the autogenerated API stub into your implementation.
Alternatively, implement the now-missing methods based on the compiler's error messages.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section for how to use features in your `Cargo.toml`.
## Documentation for API Endpoints

View File

@ -7,9 +7,9 @@ extern crate futures;
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate uuid;
extern crate clap;
extern crate tokio_core;
extern crate uuid;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};

View File

@ -21,7 +21,6 @@ extern crate chrono;
#[macro_use]
extern crate error_chain;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;

View File

@ -6,7 +6,6 @@ use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use swagger;
use swagger::{Has, XSpanIdString};

View File

@ -1,40 +1,50 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate futures;
extern crate chrono;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate mime;
#[macro_use]
extern crate serde_derive;
// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module.
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
// Crates for conversion support
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_derives;
#[cfg(feature = "conversion")]
#[macro_use]
extern crate frunk_enum_derive;
#[cfg(feature = "conversion")]
extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate chrono;
extern crate swagger;
use futures::Stream;
use std::io::Error;
#[allow(unused_imports)]
use std::collections::HashMap;
pub use futures::Future;
#[cfg(any(feature = "client", feature = "server"))]
mod mimetypes;
#[deprecated(note = "Import swagger-rs directly")]
pub use swagger::{ApiError, ContextWrapper};
#[deprecated(note = "Import futures directly")]
pub use futures::Future;
pub const BASE_PATH: &'static str = "";
pub const API_VERSION: &'static str = "2.3.4";

View File

@ -1,6 +1,5 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;
use serde::ser::Serializer;
@ -10,8 +9,8 @@ use swagger;
use std::string::ParseError;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ANullableContainer {
#[serde(rename = "NullableThing")]
#[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")]
@ -36,6 +35,7 @@ impl ANullableContainer {
/// An additionalPropertiesObject
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct AdditionalPropertiesObject {
}
@ -48,6 +48,7 @@ impl AdditionalPropertiesObject {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct InlineObject {
#[serde(rename = "id")]
pub id: String,
@ -70,6 +71,7 @@ impl InlineObject {
/// An object of objects
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ObjectOfObjects {
#[serde(rename = "inner")]
#[serde(skip_serializing_if="Option::is_none")]
@ -87,6 +89,7 @@ impl ObjectOfObjects {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct ObjectOfObjectsInner {
#[serde(rename = "required_thing")]
pub required_thing: String,

View File

@ -8,7 +8,6 @@ extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
extern crate uuid;
use std::sync::Arc;
use std::marker::PhantomData;