diff options
Diffstat (limited to 'rust/fatcat-api')
| -rw-r--r-- | rust/fatcat-api/.gitignore | 2 | ||||
| -rw-r--r-- | rust/fatcat-api/Cargo.toml | 48 | ||||
| -rw-r--r-- | rust/fatcat-api/README.md | 123 | ||||
| -rw-r--r-- | rust/fatcat-api/api.yaml | 464 | ||||
| -rw-r--r-- | rust/fatcat-api/api/swagger.yaml | 1196 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/ca.pem | 17 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/client.rs | 350 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/server-chain.pem | 66 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/server-key.pem | 28 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/server.rs | 78 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/server_lib/mod.rs | 26 | ||||
| -rw-r--r-- | rust/fatcat-api/examples/server_lib/server.rs | 287 | ||||
| -rw-r--r-- | rust/fatcat-api/src/client/mod.rs | 2573 | ||||
| -rw-r--r-- | rust/fatcat-api/src/lib.rs | 599 | ||||
| -rw-r--r-- | rust/fatcat-api/src/mimetypes.rs | 313 | ||||
| -rw-r--r-- | rust/fatcat-api/src/models.rs | 392 | ||||
| -rw-r--r-- | rust/fatcat-api/src/server/auth.rs | 93 | ||||
| -rw-r--r-- | rust/fatcat-api/src/server/mod.rs | 2485 | 
18 files changed, 9140 insertions, 0 deletions
| diff --git a/rust/fatcat-api/.gitignore b/rust/fatcat-api/.gitignore new file mode 100644 index 00000000..a9d37c56 --- /dev/null +++ b/rust/fatcat-api/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/rust/fatcat-api/Cargo.toml b/rust/fatcat-api/Cargo.toml new file mode 100644 index 00000000..8eb4279d --- /dev/null +++ b/rust/fatcat-api/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "fatcat-api" +version = "0.1.0" +authors = [] +description = "A scalable, versioned, API-oriented catalog of bibliographic entities and file metadata" +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"] + +[dependencies] +# Required by example server. +# +chrono = { version = "0.4", features = ["serde"] } +futures = "0.1" +hyper = {version = "0.11", optional = true} +hyper-tls = {version = "0.1.2", optional = true} +swagger = "0.10.0" + +# Not required by example server. +# +lazy_static = "0.2" +log = "0.3.0" +mime = "0.3.3" +multipart = {version = "0.13.3", optional = true} +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} +serde = "1.0" +serde_derive = "1.0" +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} +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 + + +[dev-dependencies] +clap = "2.25" +error-chain = "0.11" diff --git a/rust/fatcat-api/README.md b/rust/fatcat-api/README.md new file mode 100644 index 00000000..5a24942b --- /dev/null +++ b/rust/fatcat-api/README.md @@ -0,0 +1,123 @@ +# Rust API for fatcat + +A scalable, versioned, API-oriented catalog of bibliographic entities and file metadata + +## Overview +This client/server was generated by the [swagger-codegen] +(https://github.com/swagger-api/swagger-codegen) 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://github.com/swagger-api/swagger-codegen/blob/master/README.md) + +- API version: 0.1.0 +- Build date: 2018-05-15T05:47:34.699Z + +This autogenerated project defines an API crate `fatcat` which contains: +* An `Api` trait defining the API in Rust. +* Data types representing the underlying data model. +* A `Client` type which implements `Api` and issues HTTP requests for each operation. +* 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 `fatcat`: +* The example server starts up a web server using the `fatcat` 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 +  `fatcat` 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: + +``` +cargo run --example <example-name> +``` + +To pass in arguments to the examples, put them after `--`, for example: + +``` +cargo run --example client -- --help +``` + +### Running the server +To run the server, follow these simple steps: + +``` +cargo run --example server +``` + +### Running a client +To run a client, follow one of the following simple steps: + +``` +cargo run --example client ContainerIdGet +cargo run --example client ContainerLookupGet +cargo run --example client ContainerPost +cargo run --example client CreatorIdGet +cargo run --example client CreatorLookupGet +cargo run --example client CreatorPost +cargo run --example client EditgroupIdAcceptPost +cargo run --example client EditgroupIdGet +cargo run --example client EditgroupPost +cargo run --example client EditorUsernameChangelogGet +cargo run --example client EditorUsernameGet +cargo run --example client FileIdGet +cargo run --example client FileLookupGet +cargo run --example client FilePost +cargo run --example client ReleaseIdGet +cargo run --example client ReleaseLookupGet +cargo run --example client ReleasePost +cargo run --example client WorkIdGet +cargo run --example client WorkPost +``` + +### HTTPS +The examples can be run in HTTPS mode by passing in the flag `--https`, for example: + +``` +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`. + + +## Writing a server + +The server example is designed to form the basis for implementing your own server. Simply follow these steps. + +* Set up a new Rust project, e.g., with `cargo init --bin`. +* Insert `fatcat` into the `members` array under [workspace] in the root `Cargo.toml`, e.g., `members = [ "fatcat" ]`. +* Add `fatcat = {version = "0.1.0", path = "fatcat"}` under `[dependencies]` in the root `Cargo.toml`. +* Copy the `[dependencies]` and `[dev-dependencies]` from `fatcat/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 fatcat/examples/server.rs src/main.rs +cp fatcat/examples/server_lib/mod.rs src/lib.rs +cp fatcat/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. diff --git a/rust/fatcat-api/api.yaml b/rust/fatcat-api/api.yaml new file mode 100644 index 00000000..badb17ab --- /dev/null +++ b/rust/fatcat-api/api.yaml @@ -0,0 +1,464 @@ +--- +swagger: "2.0" +info: +  title: fatcat +  description: A scalable, versioned, API-oriented catalog of bibliographic entities +    and file metadata +  version: 0.1.0 +schemes: [http] +basePath: /v0 +host: api.fatcat.wiki +consumes: +  - application/json +produces: +  - application/json + + +# Common properties across entities +x-entity-props: &ENTITYPROPS +  state: +    type: string +    enum: ["wip", "active", "redirect", "deleted"] +  ident: +    type: string +    #format: uuid +  revision: +    type: integer +  redirect: +    type: string +    #format: uuid +  editgroup: +    type: integer +x-entity-edit-props: &ENTITYEDITPROPS +  id: +    type: integer +  ident: +    type: string +  revision: +    type: integer +  editgroup_id: +    type: integer + + +definitions: +  error: +    type: object +    required: +      - message +    properties: +      message: +        type: string +  success: +    type: object +    required: +      - message +    properties: +      message: +        type: string +  creator_entity: +    type: object +    properties: +      <<: *ENTITYPROPS +      name: +        type: string +      orcid: +        type: string +        #format: custom +  container_entity: +    type: object +    properties: +      <<: *ENTITYPROPS +      name: +        type: string +      parent: +        type: string +      publisher: +        type: string +      issn: +        type: string +        #format: custom +  file_entity: +    type: object +    properties: +      <<: *ENTITYPROPS +      size: +        type: integer +      sha1: +        type: string +        #format: custom +      url: +        type: string +        format: url +  release_entity: +    type: object +    properties: +      <<: *ENTITYPROPS +      work: +        type: string +      container: +        type: string +      license: +        type: string +      release_type: +        type: string +      date: +        type: date +      doi: +        type: string +        #format: custom +      volume: +        type: string +      pages: +        type: string +      issue: +        type: string +  work_entity: +    type: object +    properties: +      <<: *ENTITYPROPS +      title: +        type: string +      work_type: +        type: string +  entity_edit: +    type: object +    properties: +      <<: *ENTITYEDITPROPS +  editor: +    type: object +    required: +      - username +    properties: +      username: +        type: string +  editgroup: +    type: object +    required: +      - id +      - editor_id +    properties: +      id: +        type: integer +      editor_id: +        type: integer +  changelogentry: +    type: object +    required: +      - index +    properties: +      index: +        type: integer +      editgroup_id: +        type: integer +      timestamp: +        type: string +        format: date-time + +x-entity-responses: &ENTITYRESPONSES +  400: +    description: bad request +    schema: +      $ref: "#/definitions/error" +  default: +    description: generic error response +    schema: +      $ref: "#/definitions/error" + +paths: +  /creator: +    post: +      parameters: +        - name: body +          in: body +          schema: +            $ref: "#/definitions/creator_entity" +      responses: +        201: +          description: created +          schema: +            $ref: "#/definitions/entity_edit" +        <<: *ENTITYRESPONSES +  /creator/{id}: +    parameters: +      - name: id +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: fetch a single creator by id +          schema: +            $ref: "#/definitions/creator_entity" +        <<: *ENTITYRESPONSES +  /creator/lookup: +    get: +      parameters: +        - name: orcid +          in: query +          type: string +          required: true +      responses: +        200: +          description: find a single creator by external identifer +          schema: +            $ref: "#/definitions/creator_entity" +        404: +          description: no such creator +          schema: +            $ref: "#/definitions/error" +        <<: *ENTITYRESPONSES +  /container: +    post: +      parameters: +        - name: body +          in: body +          schema: +            $ref: "#/definitions/container_entity" +      responses: +        201: +          description: created +          schema: +            $ref: "#/definitions/entity_edit" +        <<: *ENTITYRESPONSES +  /container/{id}: +    parameters: +      - name: id +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: fetch a single container by id +          schema: +            $ref: "#/definitions/container_entity" +        <<: *ENTITYRESPONSES +  /container/lookup: +    get: +      parameters: +        - name: issn +          in: query +          type: string +          required: true +      responses: +        200: +          description: find a single container by external identifer +          schema: +            $ref: "#/definitions/container_entity" +        404: +          description: no such container +          schema: +            $ref: "#/definitions/error" +        <<: *ENTITYRESPONSES +  /file: +    post: +      parameters: +        - name: body +          in: body +          schema: +            $ref: "#/definitions/file_entity" +      responses: +        201: +          description: created +          schema: +            $ref: "#/definitions/entity_edit" +        <<: *ENTITYRESPONSES +  /file/{id}: +    parameters: +      - name: id +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: fetch a single file by id +          schema: +            $ref: "#/definitions/file_entity" +        <<: *ENTITYRESPONSES +  /file/lookup: +    get: +      parameters: +        - name: sha1 +          in: query +          type: string +          required: true +      responses: +        200: +          description: find a single file by external identifer +          schema: +            $ref: "#/definitions/file_entity" +        404: +          description: no such file +          schema: +            $ref: "#/definitions/error" +        <<: *ENTITYRESPONSES +  /release: +    post: +      parameters: +        - name: body +          in: body +          schema: +            $ref: "#/definitions/release_entity" +      responses: +        201: +          description: created +          schema: +            $ref: "#/definitions/entity_edit" +        <<: *ENTITYRESPONSES +  /release/{id}: +    parameters: +      - name: id +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: fetch a single release by id +          schema: +            $ref: "#/definitions/release_entity" +        <<: *ENTITYRESPONSES +  /release/lookup: +    get: +      parameters: +        - name: doi +          in: query +          type: string +          required: true +      responses: +        200: +          description: find a single release by external identifer +          schema: +            $ref: "#/definitions/release_entity" +        404: +          description: no such release +          schema: +            $ref: "#/definitions/error" +        <<: *ENTITYRESPONSES +  /work: +    post: +      parameters: +        - name: body +          in: body +          schema: +            $ref: "#/definitions/work_entity" +      responses: +        201: +          description: created +          schema: +            $ref: "#/definitions/entity_edit" +        <<: *ENTITYRESPONSES +  /work/{id}: +    parameters: +      - name: id +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: fetch a single work by id +          schema: +            $ref: "#/definitions/work_entity" +        <<: *ENTITYRESPONSES +  /editor/{username}: +    parameters: +      - name: username +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: fetch generic information about an editor +          schema: +            $ref: "#/definitions/editor" +        404: +          description: username not found +          schema: +            $ref: "#/definitions/error" +        default: +          description: generic error response +          schema: +            $ref: "#/definitions/error" +  /editor/{username}/changelog: +    parameters: +      - name: username +        in: path +        type: string +        required: true +    get: +      responses: +        200: +          description: find changes (editgroups) by this editor which have been merged +          schema: +            $ref: "#/definitions/changelogentry" +        404: +          description: username not found +          schema: +            $ref: "#/definitions/error" +        default: +          description: generic error response +          schema: +            $ref: "#/definitions/error" +  /editgroup: +    post: +      responses: +        201: +          description: successfully created +          schema: +            $ref: "#/definitions/editgroup" +        400: +          description: invalid request parameters +          schema: +            $ref: "#/definitions/error" +        default: +          description: generic error response +          schema: +            $ref: "#/definitions/error" +  /editgroup/{id}: +    parameters: +      - name: id +        in: path +        type: integer +        required: true +    get: +      responses: +        200: +          description: fetch editgroup by identifier +          schema: +            $ref: "#/definitions/editgroup" +        404: +          description: no such editgroup +          schema: +            $ref: "#/definitions/error" +        default: +          description: generic error response +          schema: +            $ref: "#/definitions/error" +  /editgroup/{id}/accept: +    parameters: +      - name: id +        in: path +        type: integer +        required: true +    post: +      responses: +        200: +          description: merged editgroup successfully ("live") +          schema: +            $ref: "#/definitions/success" +        400: +          description: editgroup is in an unmergable state +          schema: +            $ref: "#/definitions/error" +        404: +          description: no such editgroup +          schema: +            $ref: "#/definitions/error" +        default: +          description: generic error response +          schema: +            $ref: "#/definitions/error" diff --git a/rust/fatcat-api/api/swagger.yaml b/rust/fatcat-api/api/swagger.yaml new file mode 100644 index 00000000..66f77d5b --- /dev/null +++ b/rust/fatcat-api/api/swagger.yaml @@ -0,0 +1,1196 @@ +--- +swagger: "2.0" +info: +  description: "A scalable, versioned, API-oriented catalog of bibliographic entities\ +    \ and file metadata" +  version: "0.1.0" +  title: "fatcat" +host: "api.fatcat.wiki" +basePath: "/v0" +schemes: +- "http" +consumes: +- "application/json" +produces: +- "application/json" +paths: +  /creator: +    post: +      parameters: +      - in: "body" +        name: "body" +        required: false +        schema: +          $ref: "#/definitions/creator_entity" +        uppercase_data_type: "CREATORENTITY" +        refName: "creator_entity" +        formatString: "{:?}" +        example: "None" +        model_key: "changelogentry" +        uppercase_operation_id: "CREATOR_POST" +        consumesJson: true +      responses: +        201: +          description: "created" +          schema: +            $ref: "#/definitions/entity_edit" +          x-responseId: "Created" +          x-uppercaseResponseId: "CREATED" +          uppercase_operation_id: "CREATOR_POST" +          uppercase_data_type: "ENTITYEDIT" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "CREATOR_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "CREATOR_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "creator_post" +      uppercase_operation_id: "CREATOR_POST" +      path: "/creator" +      PATH_ID: "CREATOR" +      hasPathParams: false +      HttpMethod: "Post" +  /creator/{id}: +    get: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"id_example\".to_string()" +      responses: +        200: +          description: "fetch a single creator by id" +          schema: +            $ref: "#/definitions/creator_entity" +          x-responseId: "FetchASingleCreatorById" +          x-uppercaseResponseId: "FETCH_A_SINGLE_CREATOR_BY_ID" +          uppercase_operation_id: "CREATOR_ID_GET" +          uppercase_data_type: "CREATORENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "CREATOR_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "CREATOR_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "creator_id_get" +      uppercase_operation_id: "CREATOR_ID_GET" +      path: "/creator/:id" +      PATH_ID: "CREATOR_ID" +      hasPathParams: true +      HttpMethod: "Get" +  /creator/lookup: +    get: +      parameters: +      - name: "orcid" +        in: "query" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"orcid_example\".to_string()" +      responses: +        200: +          description: "find a single creator by external identifer" +          schema: +            $ref: "#/definitions/creator_entity" +          x-responseId: "FindASingleCreatorByExternalIdentifer" +          x-uppercaseResponseId: "FIND_A_SINGLE_CREATOR_BY_EXTERNAL_IDENTIFER" +          uppercase_operation_id: "CREATOR_LOOKUP_GET" +          uppercase_data_type: "CREATORENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "CREATOR_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        404: +          description: "no such creator" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "NoSuchCreator" +          x-uppercaseResponseId: "NO_SUCH_CREATOR" +          uppercase_operation_id: "CREATOR_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "CREATOR_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "creator_lookup_get" +      uppercase_operation_id: "CREATOR_LOOKUP_GET" +      path: "/creator/lookup" +      PATH_ID: "CREATOR_LOOKUP" +      hasPathParams: false +      HttpMethod: "Get" +  /container: +    post: +      parameters: +      - in: "body" +        name: "body" +        required: false +        schema: +          $ref: "#/definitions/container_entity" +        uppercase_data_type: "CONTAINERENTITY" +        refName: "container_entity" +        formatString: "{:?}" +        example: "None" +        model_key: "changelogentry" +        uppercase_operation_id: "CONTAINER_POST" +        consumesJson: true +      responses: +        201: +          description: "created" +          schema: +            $ref: "#/definitions/entity_edit" +          x-responseId: "Created" +          x-uppercaseResponseId: "CREATED" +          uppercase_operation_id: "CONTAINER_POST" +          uppercase_data_type: "ENTITYEDIT" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "CONTAINER_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "CONTAINER_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "container_post" +      uppercase_operation_id: "CONTAINER_POST" +      path: "/container" +      PATH_ID: "CONTAINER" +      hasPathParams: false +      HttpMethod: "Post" +  /container/{id}: +    get: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"id_example\".to_string()" +      responses: +        200: +          description: "fetch a single container by id" +          schema: +            $ref: "#/definitions/container_entity" +          x-responseId: "FetchASingleContainerById" +          x-uppercaseResponseId: "FETCH_A_SINGLE_CONTAINER_BY_ID" +          uppercase_operation_id: "CONTAINER_ID_GET" +          uppercase_data_type: "CONTAINERENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "CONTAINER_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "CONTAINER_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "container_id_get" +      uppercase_operation_id: "CONTAINER_ID_GET" +      path: "/container/:id" +      PATH_ID: "CONTAINER_ID" +      hasPathParams: true +      HttpMethod: "Get" +  /container/lookup: +    get: +      parameters: +      - name: "issn" +        in: "query" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"issn_example\".to_string()" +      responses: +        200: +          description: "find a single container by external identifer" +          schema: +            $ref: "#/definitions/container_entity" +          x-responseId: "FindASingleContainerByExternalIdentifer" +          x-uppercaseResponseId: "FIND_A_SINGLE_CONTAINER_BY_EXTERNAL_IDENTIFER" +          uppercase_operation_id: "CONTAINER_LOOKUP_GET" +          uppercase_data_type: "CONTAINERENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "CONTAINER_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        404: +          description: "no such container" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "NoSuchContainer" +          x-uppercaseResponseId: "NO_SUCH_CONTAINER" +          uppercase_operation_id: "CONTAINER_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "CONTAINER_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "container_lookup_get" +      uppercase_operation_id: "CONTAINER_LOOKUP_GET" +      path: "/container/lookup" +      PATH_ID: "CONTAINER_LOOKUP" +      hasPathParams: false +      HttpMethod: "Get" +  /file: +    post: +      parameters: +      - in: "body" +        name: "body" +        required: false +        schema: +          $ref: "#/definitions/file_entity" +        uppercase_data_type: "FILEENTITY" +        refName: "file_entity" +        formatString: "{:?}" +        example: "None" +        model_key: "changelogentry" +        uppercase_operation_id: "FILE_POST" +        consumesJson: true +      responses: +        201: +          description: "created" +          schema: +            $ref: "#/definitions/entity_edit" +          x-responseId: "Created" +          x-uppercaseResponseId: "CREATED" +          uppercase_operation_id: "FILE_POST" +          uppercase_data_type: "ENTITYEDIT" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "FILE_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "FILE_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "file_post" +      uppercase_operation_id: "FILE_POST" +      path: "/file" +      PATH_ID: "FILE" +      hasPathParams: false +      HttpMethod: "Post" +  /file/{id}: +    get: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"id_example\".to_string()" +      responses: +        200: +          description: "fetch a single file by id" +          schema: +            $ref: "#/definitions/file_entity" +          x-responseId: "FetchASingleFileById" +          x-uppercaseResponseId: "FETCH_A_SINGLE_FILE_BY_ID" +          uppercase_operation_id: "FILE_ID_GET" +          uppercase_data_type: "FILEENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "FILE_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "FILE_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "file_id_get" +      uppercase_operation_id: "FILE_ID_GET" +      path: "/file/:id" +      PATH_ID: "FILE_ID" +      hasPathParams: true +      HttpMethod: "Get" +  /file/lookup: +    get: +      parameters: +      - name: "sha1" +        in: "query" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"sha1_example\".to_string()" +      responses: +        200: +          description: "find a single file by external identifer" +          schema: +            $ref: "#/definitions/file_entity" +          x-responseId: "FindASingleFileByExternalIdentifer" +          x-uppercaseResponseId: "FIND_A_SINGLE_FILE_BY_EXTERNAL_IDENTIFER" +          uppercase_operation_id: "FILE_LOOKUP_GET" +          uppercase_data_type: "FILEENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "FILE_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        404: +          description: "no such file" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "NoSuchFile" +          x-uppercaseResponseId: "NO_SUCH_FILE" +          uppercase_operation_id: "FILE_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "FILE_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "file_lookup_get" +      uppercase_operation_id: "FILE_LOOKUP_GET" +      path: "/file/lookup" +      PATH_ID: "FILE_LOOKUP" +      hasPathParams: false +      HttpMethod: "Get" +  /release: +    post: +      parameters: +      - in: "body" +        name: "body" +        required: false +        schema: +          $ref: "#/definitions/release_entity" +        uppercase_data_type: "RELEASEENTITY" +        refName: "release_entity" +        formatString: "{:?}" +        example: "None" +        model_key: "changelogentry" +        uppercase_operation_id: "RELEASE_POST" +        consumesJson: true +      responses: +        201: +          description: "created" +          schema: +            $ref: "#/definitions/entity_edit" +          x-responseId: "Created" +          x-uppercaseResponseId: "CREATED" +          uppercase_operation_id: "RELEASE_POST" +          uppercase_data_type: "ENTITYEDIT" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "RELEASE_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "RELEASE_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "release_post" +      uppercase_operation_id: "RELEASE_POST" +      path: "/release" +      PATH_ID: "RELEASE" +      hasPathParams: false +      HttpMethod: "Post" +  /release/{id}: +    get: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"id_example\".to_string()" +      responses: +        200: +          description: "fetch a single release by id" +          schema: +            $ref: "#/definitions/release_entity" +          x-responseId: "FetchASingleReleaseById" +          x-uppercaseResponseId: "FETCH_A_SINGLE_RELEASE_BY_ID" +          uppercase_operation_id: "RELEASE_ID_GET" +          uppercase_data_type: "RELEASEENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "RELEASE_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "RELEASE_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "release_id_get" +      uppercase_operation_id: "RELEASE_ID_GET" +      path: "/release/:id" +      PATH_ID: "RELEASE_ID" +      hasPathParams: true +      HttpMethod: "Get" +  /release/lookup: +    get: +      parameters: +      - name: "doi" +        in: "query" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"doi_example\".to_string()" +      responses: +        200: +          description: "find a single release by external identifer" +          schema: +            $ref: "#/definitions/release_entity" +          x-responseId: "FindASingleReleaseByExternalIdentifer" +          x-uppercaseResponseId: "FIND_A_SINGLE_RELEASE_BY_EXTERNAL_IDENTIFER" +          uppercase_operation_id: "RELEASE_LOOKUP_GET" +          uppercase_data_type: "RELEASEENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "RELEASE_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        404: +          description: "no such release" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "NoSuchRelease" +          x-uppercaseResponseId: "NO_SUCH_RELEASE" +          uppercase_operation_id: "RELEASE_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "RELEASE_LOOKUP_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "release_lookup_get" +      uppercase_operation_id: "RELEASE_LOOKUP_GET" +      path: "/release/lookup" +      PATH_ID: "RELEASE_LOOKUP" +      hasPathParams: false +      HttpMethod: "Get" +  /work: +    post: +      parameters: +      - in: "body" +        name: "body" +        required: false +        schema: +          $ref: "#/definitions/work_entity" +        uppercase_data_type: "WORKENTITY" +        refName: "work_entity" +        formatString: "{:?}" +        example: "None" +        model_key: "changelogentry" +        uppercase_operation_id: "WORK_POST" +        consumesJson: true +      responses: +        201: +          description: "created" +          schema: +            $ref: "#/definitions/entity_edit" +          x-responseId: "Created" +          x-uppercaseResponseId: "CREATED" +          uppercase_operation_id: "WORK_POST" +          uppercase_data_type: "ENTITYEDIT" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "WORK_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "WORK_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "work_post" +      uppercase_operation_id: "WORK_POST" +      path: "/work" +      PATH_ID: "WORK" +      hasPathParams: false +      HttpMethod: "Post" +  /work/{id}: +    get: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"id_example\".to_string()" +      responses: +        200: +          description: "fetch a single work by id" +          schema: +            $ref: "#/definitions/work_entity" +          x-responseId: "FetchASingleWorkById" +          x-uppercaseResponseId: "FETCH_A_SINGLE_WORK_BY_ID" +          uppercase_operation_id: "WORK_ID_GET" +          uppercase_data_type: "WORKENTITY" +          producesJson: true +        400: +          description: "bad request" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "BadRequest" +          x-uppercaseResponseId: "BAD_REQUEST" +          uppercase_operation_id: "WORK_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "WORK_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "work_id_get" +      uppercase_operation_id: "WORK_ID_GET" +      path: "/work/:id" +      PATH_ID: "WORK_ID" +      hasPathParams: true +      HttpMethod: "Get" +  /editor/{username}: +    get: +      parameters: +      - name: "username" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"username_example\".to_string()" +      responses: +        200: +          description: "fetch generic information about an editor" +          schema: +            $ref: "#/definitions/editor" +          x-responseId: "FetchGenericInformationAboutAnEditor" +          x-uppercaseResponseId: "FETCH_GENERIC_INFORMATION_ABOUT_AN_EDITOR" +          uppercase_operation_id: "EDITOR_USERNAME_GET" +          uppercase_data_type: "EDITOR" +          producesJson: true +        404: +          description: "username not found" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "UsernameNotFound" +          x-uppercaseResponseId: "USERNAME_NOT_FOUND" +          uppercase_operation_id: "EDITOR_USERNAME_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "EDITOR_USERNAME_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "editor_username_get" +      uppercase_operation_id: "EDITOR_USERNAME_GET" +      path: "/editor/:username" +      PATH_ID: "EDITOR_USERNAME" +      hasPathParams: true +      HttpMethod: "Get" +  /editor/{username}/changelog: +    get: +      parameters: +      - name: "username" +        in: "path" +        required: true +        type: "string" +        formatString: "\\\"{}\\\"" +        example: "\"username_example\".to_string()" +      responses: +        200: +          description: "find changes (editgroups) by this editor which have been merged" +          schema: +            $ref: "#/definitions/changelogentry" +          x-responseId: "FindChanges_" +          x-uppercaseResponseId: "FIND_CHANGES_" +          uppercase_operation_id: "EDITOR_USERNAME_CHANGELOG_GET" +          uppercase_data_type: "CHANGELOGENTRY" +          producesJson: true +        404: +          description: "username not found" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "UsernameNotFound" +          x-uppercaseResponseId: "USERNAME_NOT_FOUND" +          uppercase_operation_id: "EDITOR_USERNAME_CHANGELOG_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "EDITOR_USERNAME_CHANGELOG_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "editor_username_changelog_get" +      uppercase_operation_id: "EDITOR_USERNAME_CHANGELOG_GET" +      path: "/editor/:username/changelog" +      PATH_ID: "EDITOR_USERNAME_CHANGELOG" +      hasPathParams: true +      HttpMethod: "Get" +  /editgroup: +    post: +      parameters: [] +      responses: +        201: +          description: "successfully created" +          schema: +            $ref: "#/definitions/editgroup" +          x-responseId: "SuccessfullyCreated" +          x-uppercaseResponseId: "SUCCESSFULLY_CREATED" +          uppercase_operation_id: "EDITGROUP_POST" +          uppercase_data_type: "EDITGROUP" +          producesJson: true +        400: +          description: "invalid request parameters" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "InvalidRequestParameters" +          x-uppercaseResponseId: "INVALID_REQUEST_PARAMETERS" +          uppercase_operation_id: "EDITGROUP_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "EDITGROUP_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "editgroup_post" +      uppercase_operation_id: "EDITGROUP_POST" +      path: "/editgroup" +      PATH_ID: "EDITGROUP" +      hasPathParams: false +      HttpMethod: "Post" +  /editgroup/{id}: +    get: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "integer" +        formatString: "{}" +        example: "56" +      responses: +        200: +          description: "fetch editgroup by identifier" +          schema: +            $ref: "#/definitions/editgroup" +          x-responseId: "FetchEditgroupByIdentifier" +          x-uppercaseResponseId: "FETCH_EDITGROUP_BY_IDENTIFIER" +          uppercase_operation_id: "EDITGROUP_ID_GET" +          uppercase_data_type: "EDITGROUP" +          producesJson: true +        404: +          description: "no such editgroup" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "NoSuchEditgroup" +          x-uppercaseResponseId: "NO_SUCH_EDITGROUP" +          uppercase_operation_id: "EDITGROUP_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "EDITGROUP_ID_GET" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "editgroup_id_get" +      uppercase_operation_id: "EDITGROUP_ID_GET" +      path: "/editgroup/:id" +      PATH_ID: "EDITGROUP_ID" +      hasPathParams: true +      HttpMethod: "Get" +  /editgroup/{id}/accept: +    post: +      parameters: +      - name: "id" +        in: "path" +        required: true +        type: "integer" +        formatString: "{}" +        example: "56" +      responses: +        200: +          description: "merged editgroup successfully (\"live\")" +          schema: +            $ref: "#/definitions/success" +          x-responseId: "MergedEditgroupSuccessfully_" +          x-uppercaseResponseId: "MERGED_EDITGROUP_SUCCESSFULLY_" +          uppercase_operation_id: "EDITGROUP_ID_ACCEPT_POST" +          uppercase_data_type: "SUCCESS" +          producesJson: true +        400: +          description: "editgroup is in an unmergable state" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "EditgroupIsInAnUnmergableState" +          x-uppercaseResponseId: "EDITGROUP_IS_IN_AN_UNMERGABLE_STATE" +          uppercase_operation_id: "EDITGROUP_ID_ACCEPT_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        404: +          description: "no such editgroup" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "NoSuchEditgroup" +          x-uppercaseResponseId: "NO_SUCH_EDITGROUP" +          uppercase_operation_id: "EDITGROUP_ID_ACCEPT_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +        default: +          description: "generic error response" +          schema: +            $ref: "#/definitions/error" +          x-responseId: "GenericErrorResponse" +          x-uppercaseResponseId: "GENERIC_ERROR_RESPONSE" +          uppercase_operation_id: "EDITGROUP_ID_ACCEPT_POST" +          uppercase_data_type: "ERROR" +          producesJson: true +      operation_id: "editgroup_id_accept_post" +      uppercase_operation_id: "EDITGROUP_ID_ACCEPT_POST" +      path: "/editgroup/:id/accept" +      PATH_ID: "EDITGROUP_ID_ACCEPT" +      hasPathParams: true +      HttpMethod: "Post" +definitions: +  error: +    type: "object" +    required: +    - "message" +    properties: +      message: +        type: "string" +    upperCaseName: "ERROR" +  success: +    type: "object" +    required: +    - "message" +    properties: +      message: +        type: "string" +    example: +      message: "message" +    upperCaseName: "SUCCESS" +  creator_entity: +    type: "object" +    properties: +      orcid: +        type: "string" +      name: +        type: "string" +      editgroup: +        type: "integer" +      redirect: +        type: "string" +      revision: +        type: "integer" +      ident: +        type: "string" +      state: +        type: "string" +        enum: +        - "wip" +        - "active" +        - "redirect" +        - "deleted" +    example: +      redirect: "redirect" +      editgroup: 0 +      ident: "ident" +      name: "name" +      orcid: "orcid" +      state: "wip" +      revision: 6 +    upperCaseName: "CREATOR_ENTITY" +  container_entity: +    type: "object" +    properties: +      issn: +        type: "string" +      publisher: +        type: "string" +      parent: +        type: "string" +      name: +        type: "string" +      state: +        type: "string" +        enum: +        - "wip" +        - "active" +        - "redirect" +        - "deleted" +      ident: +        type: "string" +      revision: +        type: "integer" +      redirect: +        type: "string" +      editgroup: +        type: "integer" +    example: +      redirect: "redirect" +      parent: "parent" +      editgroup: 6 +      issn: "issn" +      ident: "ident" +      name: "name" +      publisher: "publisher" +      state: "wip" +      revision: 0 +    upperCaseName: "CONTAINER_ENTITY" +  file_entity: +    type: "object" +    properties: +      url: +        type: "string" +        format: "url" +      sha1: +        type: "string" +      size: +        type: "integer" +      editgroup: +        type: "integer" +      redirect: +        type: "string" +      revision: +        type: "integer" +      ident: +        type: "string" +      state: +        type: "string" +        enum: +        - "wip" +        - "active" +        - "redirect" +        - "deleted" +    example: +      sha1: "sha1" +      redirect: "redirect" +      editgroup: 6 +      size: 0 +      ident: "ident" +      state: "wip" +      url: "http://example.com/aeiou" +      revision: 1 +    upperCaseName: "FILE_ENTITY" +  release_entity: +    type: "object" +    properties: +      issue: +        type: "string" +      pages: +        type: "string" +      volume: +        type: "string" +      doi: +        type: "string" +      release_type: +        type: "string" +      license: +        type: "string" +      container: +        type: "string" +      work: +        type: "string" +      state: +        type: "string" +        enum: +        - "wip" +        - "active" +        - "redirect" +        - "deleted" +      ident: +        type: "string" +      revision: +        type: "integer" +      redirect: +        type: "string" +      editgroup: +        type: "integer" +    example: +      container: "container" +      redirect: "redirect" +      editgroup: 6 +      issue: "issue" +      work: "work" +      ident: "ident" +      release_type: "release_type" +      revision: 0 +      volume: "volume" +      license: "license" +      pages: "pages" +      state: "wip" +      doi: "doi" +    upperCaseName: "RELEASE_ENTITY" +  work_entity: +    type: "object" +    properties: +      work_type: +        type: "string" +      title: +        type: "string" +      editgroup: +        type: "integer" +      redirect: +        type: "string" +      revision: +        type: "integer" +      ident: +        type: "string" +      state: +        type: "string" +        enum: +        - "wip" +        - "active" +        - "redirect" +        - "deleted" +    example: +      redirect: "redirect" +      editgroup: 0 +      ident: "ident" +      work_type: "work_type" +      state: "wip" +      title: "title" +      revision: 6 +    upperCaseName: "WORK_ENTITY" +  entity_edit: +    type: "object" +    properties: +      editgroup_id: +        type: "integer" +      revision: +        type: "integer" +      ident: +        type: "string" +      id: +        type: "integer" +    example: +      ident: "ident" +      editgroup_id: 0 +      id: 1 +      revision: 6 +    upperCaseName: "ENTITY_EDIT" +  editor: +    type: "object" +    required: +    - "username" +    properties: +      username: +        type: "string" +    example: +      username: "username" +    upperCaseName: "EDITOR" +  editgroup: +    type: "object" +    required: +    - "editor_id" +    - "id" +    properties: +      id: +        type: "integer" +      editor_id: +        type: "integer" +    example: +      editor_id: 6 +      id: 0 +    upperCaseName: "EDITGROUP" +  changelogentry: +    type: "object" +    required: +    - "index" +    properties: +      index: +        type: "integer" +      editgroup_id: +        type: "integer" +      timestamp: +        type: "string" +        format: "date-time" +    example: +      index: 0 +      editgroup_id: 6 +      timestamp: "2000-01-23T04:56:07.000+00:00" +    upperCaseName: "CHANGELOGENTRY" +x-entity-props: +  state: +    type: "string" +    enum: +    - "wip" +    - "active" +    - "redirect" +    - "deleted" +  ident: +    type: "string" +  revision: +    type: "integer" +  redirect: +    type: "string" +  editgroup: +    type: "integer" +x-entity-edit-props: +  id: +    type: "integer" +  ident: +    type: "string" +  revision: +    type: "integer" +  editgroup_id: +    type: "integer" +x-entity-responses: +  400: +    description: "bad request" +    schema: +      $ref: "#/definitions/error" +  default: +    description: "generic error response" +    schema: +      $ref: "#/definitions/error" diff --git a/rust/fatcat-api/examples/ca.pem b/rust/fatcat-api/examples/ca.pem new file mode 100644 index 00000000..d2317fb5 --- /dev/null +++ b/rust/fatcat-api/examples/ca.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtjCCAZ4CCQDpKecRERZ0xDANBgkqhkiG9w0BAQsFADAdMQswCQYDVQQGEwJV +UzEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwNTIzMTYwMDIzWhcNMTcwNjIyMTYwMDIz +WjAdMQswCQYDVQQGEwJVUzEOMAwGA1UEAxMFTXkgQ0EwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCt66py3x7sCSASRF2D05L5wkNDxAUjQKYx23W8Gbwv +GMGykk89BIdU5LX1JB1cKiUOkoIxfwAYuWc2V/wzTvVV7+11besnk3uX1c9KiqUF +LIX7kn/z5hzS4aelhKvH+MJlSZCSlp1ytpZbwo5GB5Pi2SGH56jDBiBoDRNBVdWL +z4wH7TdrQjqWwNxIZumD5OGMtcfJyuX08iPiEOaslOeoMqzObhvjc9aUgjVjhqyA +FkJGTXsi0oaD7oml+NE+mTNfEeZvEJQpLSjBY0OvQHzuHkyGBShBnfu/9x7/NRwd +WaqsLiF7/re9KDGYdJwP7Cu6uxYfKAyWarp6h2mG/GIdAgMBAAEwDQYJKoZIhvcN +AQELBQADggEBAGIl/VVIafeq/AJOQ9r7TzzB2ABJYr7NZa6bTu5O1jSp1Fonac15 +SZ8gvRxODgH22ZYSqghPG4xzq4J3hkytlQqm57ZEt2I2M3OqIp17Ndcc1xDYzpLl +tA0FrVn6crQTM8vQkTDtGesaCWX+7Fir5dK7HnYWzfpSmsOpST07PfbNisEXKOxG +Dj4lBL1OnhTjsJeymVS1pFvkKkrcEJO+IxFiHL3CDsWjcXB0Z+E1zBtPoYyYsNsO +rBrjUxcZewF4xqWZhpW90Mt61fY2nRgU0uUwHcvDQUqvmzKcsqYa4mPKzfBI5mxo +01Ta96cDD6pS5Y1hOflZ0g84f2g/7xBLLDA= +-----END CERTIFICATE----- diff --git a/rust/fatcat-api/examples/client.rs b/rust/fatcat-api/examples/client.rs new file mode 100644 index 00000000..6f7aa151 --- /dev/null +++ b/rust/fatcat-api/examples/client.rs @@ -0,0 +1,350 @@ +#![allow(missing_docs, unused_variables, trivial_casts)] + +extern crate clap; +extern crate fatcat; +#[allow(unused_extern_crates)] +extern crate futures; +#[allow(unused_extern_crates)] +extern crate swagger; +extern crate tokio_core; +#[allow(unused_extern_crates)] +extern crate uuid; + +use clap::{App, Arg}; +#[allow(unused_imports)] +use fatcat::{ApiError, ApiNoContext, ContainerIdGetResponse, ContainerLookupGetResponse, +             ContainerPostResponse, ContextWrapperExt, CreatorIdGetResponse, +             CreatorLookupGetResponse, CreatorPostResponse, EditgroupIdAcceptPostResponse, +             EditgroupIdGetResponse, EditgroupPostResponse, EditorUsernameChangelogGetResponse, +             EditorUsernameGetResponse, FileIdGetResponse, FileLookupGetResponse, +             FilePostResponse, ReleaseIdGetResponse, ReleaseLookupGetResponse, +             ReleasePostResponse, WorkIdGetResponse, WorkPostResponse}; +#[allow(unused_imports)] +use futures::{future, stream, Future, Stream}; +use tokio_core::reactor; + +fn main() { +    let matches = App::new("client") +        .arg( +            Arg::with_name("operation") +                .help("Sets the operation to run") +                .possible_values(&[ +                    "ContainerIdGet", +                    "ContainerLookupGet", +                    "ContainerPost", +                    "CreatorIdGet", +                    "CreatorLookupGet", +                    "CreatorPost", +                    "EditgroupIdAcceptPost", +                    "EditgroupIdGet", +                    "EditgroupPost", +                    "EditorUsernameChangelogGet", +                    "EditorUsernameGet", +                    "FileIdGet", +                    "FileLookupGet", +                    "FilePost", +                    "ReleaseIdGet", +                    "ReleaseLookupGet", +                    "ReleasePost", +                    "WorkIdGet", +                    "WorkPost", +                ]) +                .required(true) +                .index(1), +        ) +        .arg( +            Arg::with_name("https") +                .long("https") +                .help("Whether to use HTTPS or not"), +        ) +        .arg( +            Arg::with_name("host") +                .long("host") +                .takes_value(true) +                .default_value("api.fatcat.wiki") +                .help("Hostname to contact"), +        ) +        .arg( +            Arg::with_name("port") +                .long("port") +                .takes_value(true) +                .default_value("8080") +                .help("Port to contact"), +        ) +        .get_matches(); + +    let mut core = reactor::Core::new().unwrap(); +    let is_https = matches.is_present("https"); +    let base_url = format!( +        "{}://{}:{}", +        if is_https { "https" } else { "http" }, +        matches.value_of("host").unwrap(), +        matches.value_of("port").unwrap() +    ); +    let client = if matches.is_present("https") { +        // Using Simple HTTPS +        fatcat::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem") +            .expect("Failed to create HTTPS client") +    } else { +        // Using HTTP +        fatcat::Client::try_new_http(core.handle(), &base_url) +            .expect("Failed to create HTTP client") +    }; + +    // Using a non-default `Context` is not required; this is just an example! +    let client = client.with_context(fatcat::Context::new_with_span_id( +        self::uuid::Uuid::new_v4().to_string(), +    )); + +    match matches.value_of("operation") { +        Some("ContainerIdGet") => { +            let result = core.run(client.container_id_get("id_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("ContainerLookupGet") => { +            let result = core.run(client.container_lookup_get("issn_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("ContainerPost") => { +            let result = core.run(client.container_post(None)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("CreatorIdGet") => { +            let result = core.run(client.creator_id_get("id_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("CreatorLookupGet") => { +            let result = core.run(client.creator_lookup_get("orcid_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("CreatorPost") => { +            let result = core.run(client.creator_post(None)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("EditgroupIdAcceptPost") => { +            let result = core.run(client.editgroup_id_accept_post(56)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("EditgroupIdGet") => { +            let result = core.run(client.editgroup_id_get(56)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("EditgroupPost") => { +            let result = core.run(client.editgroup_post()); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("EditorUsernameChangelogGet") => { +            let result = +                core.run(client.editor_username_changelog_get("username_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("EditorUsernameGet") => { +            let result = core.run(client.editor_username_get("username_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("FileIdGet") => { +            let result = core.run(client.file_id_get("id_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("FileLookupGet") => { +            let result = core.run(client.file_lookup_get("sha1_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("FilePost") => { +            let result = core.run(client.file_post(None)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("ReleaseIdGet") => { +            let result = core.run(client.release_id_get("id_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("ReleaseLookupGet") => { +            let result = core.run(client.release_lookup_get("doi_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("ReleasePost") => { +            let result = core.run(client.release_post(None)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("WorkIdGet") => { +            let result = core.run(client.work_id_get("id_example".to_string())); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        Some("WorkPost") => { +            let result = core.run(client.work_post(None)); +            println!( +                "{:?} (X-Span-ID: {:?})", +                result, +                client +                    .context() +                    .x_span_id +                    .clone() +                    .unwrap_or(String::from("<none>")) +            ); +        } + +        _ => panic!("Invalid operation provided"), +    } +} diff --git a/rust/fatcat-api/examples/server-chain.pem b/rust/fatcat-api/examples/server-chain.pem new file mode 100644 index 00000000..47d7e201 --- /dev/null +++ b/rust/fatcat-api/examples/server-chain.pem @@ -0,0 +1,66 @@ +Certificate: +    Data: +        Version: 1 (0x0) +        Serial Number: 4096 (0x1000) +    Signature Algorithm: sha256WithRSAEncryption +        Issuer: C=US, CN=My CA +        Validity +            Not Before: May 23 16:00:23 2017 GMT +            Not After : Apr 29 16:00:23 2117 GMT +        Subject: CN=localhost, C=US +        Subject Public Key Info: +            Public Key Algorithm: rsaEncryption +                Public-Key: (2048 bit) +                Modulus: +                    00:c9:d4:43:60:50:fc:d6:0f:38:4d:5d:5e:aa:7c: +                    c0:5e:a9:ec:d9:93:78:d3:93:72:28:41:f5:08:a5: +                    ea:ac:67:07:d7:1f:f7:7d:74:69:7e:46:89:20:4b: +                    7a:2d:9b:02:08:e7:6f:0f:1d:0c:0f:c7:60:69:19: +                    4b:df:7e:ca:75:94:0b:49:71:e3:6d:f2:e8:79:fd: +                    ed:0a:94:67:55:f3:ca:6b:61:ba:58:b7:2e:dd:7b: +                    ca:b9:02:9f:24:36:ac:26:8f:04:8f:81:c8:35:10: +                    f4:aa:33:b2:24:16:f8:f7:1e:ea:f7:16:fe:fa:34: +                    c3:dd:bb:2c:ba:7a:df:4d:e2:da:1e:e5:d2:28:44: +                    6e:c8:96:e0:fd:09:0c:14:0c:31:dc:e0:ca:c1:a7: +                    9b:bf:16:8c:f7:36:3f:1b:2e:dd:90:eb:45:78:51: +                    bf:59:22:1e:c6:8c:0a:69:88:e5:03:5e:73:b7:fc: +                    93:7f:1b:46:1b:97:68:c5:c0:8b:35:1f:bb:1e:67: +                    7f:55:b7:3b:55:3f:ea:f2:ca:db:cc:52:cd:16:89: +                    db:15:47:bd:f2:cd:6c:7a:d7:b4:1a:ac:c8:15:6c: +                    6a:fb:77:c4:e9:f2:30:e0:14:24:66:65:6f:2a:e5: +                    2d:cc:f6:81:ae:57:c8:d1:9b:38:90:dc:60:93:02: +                    5e:cb +                Exponent: 65537 (0x10001) +    Signature Algorithm: sha256WithRSAEncryption +         1c:7c:39:e8:3d:49:b2:09:1e:68:5a:2f:74:18:f4:63:b5:8c: +         f6:e6:a1:e3:4d:95:90:99:ef:32:5c:34:40:e8:55:13:0e:e0: +         1c:be:cd:ab:3f:64:38:99:5e:2b:c1:81:53:a0:18:a8:f6:ee: +         6a:33:73:6c:9a:73:9d:86:08:5d:c7:11:38:46:4c:cd:a0:47: +         37:8f:fe:a6:50:a9:02:21:99:42:86:5e:47:fe:65:56:60:1d: +         16:53:86:bd:e4:63:c5:69:cf:fa:30:51:ab:a1:c3:50:53:cc: +         66:1c:4c:ff:3f:2a:39:4d:a2:8f:9d:d1:a7:8b:22:e4:78:69: +         24:06:83:4d:cc:0a:c0:87:69:9b:bc:80:a9:d2:b7:a5:23:84: +         7e:a2:32:26:7c:78:0e:bd:db:cd:3b:69:18:33:b8:44:ef:96: +         b4:99:86:ee:06:bd:51:1c:c7:a1:a4:0c:c4:4c:51:a0:df:ac: +         14:07:88:8e:d7:39:45:fe:52:e0:a3:4c:db:5d:7a:ab:4d:e4: +         ca:06:e8:bd:74:6f:46:e7:93:4a:4f:1b:67:e7:a5:9f:ef:9c: +         02:49:d1:f2:d5:e9:53:ee:09:21:ac:08:c8:15:f7:af:35:b9: +         4f:11:0f:43:ae:46:8e:fd:5b:8d:a3:4e:a7:2c:b7:25:ed:e4: +         e5:94:1d:e3 +-----BEGIN CERTIFICATE----- +MIICtTCCAZ0CAhAAMA0GCSqGSIb3DQEBCwUAMB0xCzAJBgNVBAYTAlVTMQ4wDAYD +VQQDEwVNeSBDQTAgFw0xNzA1MjMxNjAwMjNaGA8yMTE3MDQyOTE2MDAyM1owITES +MBAGA1UEAxMJbG9jYWxob3N0MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMnUQ2BQ/NYPOE1dXqp8wF6p7NmTeNOTcihB9Qil6qxn +B9cf9310aX5GiSBLei2bAgjnbw8dDA/HYGkZS99+ynWUC0lx423y6Hn97QqUZ1Xz +ymthuli3Lt17yrkCnyQ2rCaPBI+ByDUQ9KozsiQW+Pce6vcW/vo0w927LLp6303i +2h7l0ihEbsiW4P0JDBQMMdzgysGnm78WjPc2Pxsu3ZDrRXhRv1kiHsaMCmmI5QNe +c7f8k38bRhuXaMXAizUfux5nf1W3O1U/6vLK28xSzRaJ2xVHvfLNbHrXtBqsyBVs +avt3xOnyMOAUJGZlbyrlLcz2ga5XyNGbOJDcYJMCXssCAwEAATANBgkqhkiG9w0B +AQsFAAOCAQEAHHw56D1JsgkeaFovdBj0Y7WM9uah402VkJnvMlw0QOhVEw7gHL7N +qz9kOJleK8GBU6AYqPbuajNzbJpznYYIXccROEZMzaBHN4/+plCpAiGZQoZeR/5l +VmAdFlOGveRjxWnP+jBRq6HDUFPMZhxM/z8qOU2ij53Rp4si5HhpJAaDTcwKwIdp +m7yAqdK3pSOEfqIyJnx4Dr3bzTtpGDO4RO+WtJmG7ga9URzHoaQMxExRoN+sFAeI +jtc5Rf5S4KNM2116q03kygbovXRvRueTSk8bZ+eln++cAknR8tXpU+4JIawIyBX3 +rzW5TxEPQ65Gjv1bjaNOpyy3Je3k5ZQd4w== +-----END CERTIFICATE----- diff --git a/rust/fatcat-api/examples/server-key.pem b/rust/fatcat-api/examples/server-key.pem new file mode 100644 index 00000000..29c00682 --- /dev/null +++ b/rust/fatcat-api/examples/server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJ1ENgUPzWDzhN +XV6qfMBeqezZk3jTk3IoQfUIpeqsZwfXH/d9dGl+RokgS3otmwII528PHQwPx2Bp +GUvffsp1lAtJceNt8uh5/e0KlGdV88prYbpYty7de8q5Ap8kNqwmjwSPgcg1EPSq +M7IkFvj3Hur3Fv76NMPduyy6et9N4toe5dIoRG7IluD9CQwUDDHc4MrBp5u/Foz3 +Nj8bLt2Q60V4Ub9ZIh7GjAppiOUDXnO3/JN/G0Ybl2jFwIs1H7seZ39VtztVP+ry +ytvMUs0WidsVR73yzWx617QarMgVbGr7d8Tp8jDgFCRmZW8q5S3M9oGuV8jRmziQ +3GCTAl7LAgMBAAECggEBAKEd1q9j14KWYc64s6KLthGbutyxsinMMbxbct11fdIk +6YhdF3fJ35ETg9IJDr6rWEN9ZRX+jStncNpVfFEs6ThVd3Eo/nI+EEGaaIkikR93 +X2a7fEPn7/yVHu70XdBN6L1bPDvHUeiy4W2hmRrgT90OjGm1rNRWHOm7yugOwIZu +HclzbR9Ca7EInFnotUiDQm9sw9VKHbJHqWx6OORdZrxR2ytYs0Qkq0XpGMvti2HW +7WAmKTg5QM8myXW7+/4iqb/u68wVBR2BBalShKmIf7lim9O3W2a1RjDdsvm/wNe9 +I+D+Iq825vpqkKXcrxYlpVg7hYiaQaW/MNsEb7lQRjECgYEA/RJYby0POW+/k0Jn +jO8UmJVEMiuGa8WIUu/JJWMOmzRCukjSRNQOkt7niQrZPJYE8W6clM6RJTolWf9L +IL6mIb+mRaoudUk8SHGDq7ho1iMg9GK8lhYxvKh1Q6uv8EyVSkgLknAEY0NANKC1 +zNdU5Dhven9aRX2gq9vP4XwMz2MCgYEAzCogQ7IFk+gkp3k491dOZnrGRoRCfuzo +4CJtyKFgOSd7BjmpcKkj0IPfVBjw6GjMIxfQRMTQmxAjjWevH45vG8l0Iiwz/gSp +81b5nsDEX5uv2Olcmcz5zxRFy36jOZ9ihMWinxcIlT2oDbyCdbruDKZq9ieJ9S8g +4qGx0OkwE3kCgYEA7CmAiU89U9YqqttfEq/RQoqY91CSwmO10d+ej9seuEtOsdRf +FIfnibulycdr7hP5TOxyBpO1802NqayJiWcgVYIpQf2MGTtcnCYCP+95NcvWZvj1 +EAJqK6nwtFO1fcOZ1ZXh5qfOEGujsPkAbsXLnKXlsiTCMvMHSxl3pu5Cbg0CgYBf +JjbZNctRrjv+7Qj2hPLd4dQsIxGWc7ToWENP4J2mpVa5hQAJqFovoHXhjKohtk2F +AWEn243Y5oGbMjo0e74edhmwn2cvuF64MM2vBem/ISCn98IXT6cQskMA3qkVfsl8 +VVs/x41ReGWs2TD3y0GMFbb9t1mdMfSiincDhNnKCQKBgGfeT4jKyYeCoCw4OLI1 +G75Gd0METt/IkppwODPpNwj3Rp9I5jctWZFA/3wCX/zk0HgBeou5AFNS4nQZ/X/L +L9axbSdR7UJTGkT1r4gu3rLkPV4Tk+8XM03/JT2cofMlzQBuhvl1Pn4SgKowz7hl +lS76ECw4Av3T0S34VW9Z5oye +-----END PRIVATE KEY----- diff --git a/rust/fatcat-api/examples/server.rs b/rust/fatcat-api/examples/server.rs new file mode 100644 index 00000000..f9b8617c --- /dev/null +++ b/rust/fatcat-api/examples/server.rs @@ -0,0 +1,78 @@ +//! Main binary entry point for fatcat implementation. + +#![allow(missing_docs)] + +// Imports required by this file. +// extern crate <name of this crate>; +extern crate clap; +extern crate fatcat; +extern crate hyper; +extern crate native_tls; +extern crate openssl; +extern crate swagger; +extern crate tokio_proto; +extern crate tokio_tls; + +// Imports required by server library. +// extern crate fatcat; +// extern crate swagger; +extern crate chrono; +extern crate futures; +#[macro_use] +extern crate error_chain; + +use clap::{App, Arg}; +use hyper::server::Http; +use openssl::error::ErrorStack; +use openssl::ssl::{SslAcceptorBuilder, SslMethod}; +use openssl::x509::X509_FILETYPE_PEM; +use swagger::auth::AllowAllAuthenticator; +use tokio_proto::TcpServer; + +mod server_lib; + +// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +fn ssl() -> Result<SslAcceptorBuilder, ErrorStack> { +    let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; + +    // Server authentication +    ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; +    ssl.set_certificate_chain_file("examples/server-chain.pem")?; +    ssl.check_private_key()?; + +    Ok(ssl) +} + +/// Create custom server, wire it to the autogenerated router, +/// and pass it to the web server. +fn main() { +    let matches = App::new("server") +        .arg( +            Arg::with_name("https") +                .long("https") +                .help("Whether to use HTTPS or not"), +        ) +        .get_matches(); + +    let service_fn = fatcat::server::auth::NewService::new(AllowAllAuthenticator::new( +        server_lib::NewService, +        "cosmo", +    )); + +    let addr = "127.0.0.1:8080" +        .parse() +        .expect("Failed to parse bind address"); +    if matches.is_present("https") { +        let ssl = ssl().expect("Failed to load SSL keys"); +        let builder: native_tls::TlsAcceptorBuilder = +            native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl); +        let tls_acceptor = builder.build().expect("Failed to build TLS acceptor"); +        TcpServer::new( +            tokio_tls::proto::Server::new(Http::new(), tls_acceptor), +            addr, +        ).serve(service_fn); +    } else { +        // Using HTTP +        TcpServer::new(Http::new(), addr).serve(service_fn); +    } +} diff --git a/rust/fatcat-api/examples/server_lib/mod.rs b/rust/fatcat-api/examples/server_lib/mod.rs new file mode 100644 index 00000000..a45fbe50 --- /dev/null +++ b/rust/fatcat-api/examples/server_lib/mod.rs @@ -0,0 +1,26 @@ +//! Main library entry point for fatcat implementation. + +mod server; + +mod errors { +    error_chain!{} +} + +pub use self::errors::*; +use fatcat; +use hyper; +use std::io; + +pub struct NewService; + +impl hyper::server::NewService for NewService { +    type Request = (hyper::Request, fatcat::Context); +    type Response = hyper::Response; +    type Error = hyper::Error; +    type Instance = fatcat::server::Service<server::Server>; + +    /// Instantiate a new server. +    fn new_service(&self) -> io::Result<Self::Instance> { +        Ok(fatcat::server::Service::new(server::Server)) +    } +} diff --git a/rust/fatcat-api/examples/server_lib/server.rs b/rust/fatcat-api/examples/server_lib/server.rs new file mode 100644 index 00000000..0dec7ed3 --- /dev/null +++ b/rust/fatcat-api/examples/server_lib/server.rs @@ -0,0 +1,287 @@ +//! Server implementation of fatcat. + +#![allow(unused_imports)] + +use chrono; +use futures::{self, Future}; + +use std::collections::HashMap; + +use swagger; + +use fatcat::models; +use fatcat::{Api, ApiError, ContainerIdGetResponse, ContainerLookupGetResponse, +             ContainerPostResponse, Context, CreatorIdGetResponse, CreatorLookupGetResponse, +             CreatorPostResponse, EditgroupIdAcceptPostResponse, EditgroupIdGetResponse, +             EditgroupPostResponse, EditorUsernameChangelogGetResponse, EditorUsernameGetResponse, +             FileIdGetResponse, FileLookupGetResponse, FilePostResponse, ReleaseIdGetResponse, +             ReleaseLookupGetResponse, ReleasePostResponse, WorkIdGetResponse, WorkPostResponse}; + +#[derive(Copy, Clone)] +pub struct Server; + +impl Api for Server { +    fn container_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = ContainerIdGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "container_id_get(\"{}\") - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn container_lookup_get( +        &self, +        issn: String, +        context: &Context, +    ) -> Box<Future<Item = ContainerLookupGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "container_lookup_get(\"{}\") - X-Span-ID: {:?}", +            issn, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn container_post( +        &self, +        body: Option<models::ContainerEntity>, +        context: &Context, +    ) -> Box<Future<Item = ContainerPostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "container_post({:?}) - X-Span-ID: {:?}", +            body, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn creator_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = CreatorIdGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "creator_id_get(\"{}\") - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn creator_lookup_get( +        &self, +        orcid: String, +        context: &Context, +    ) -> Box<Future<Item = CreatorLookupGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "creator_lookup_get(\"{}\") - X-Span-ID: {:?}", +            orcid, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn creator_post( +        &self, +        body: Option<models::CreatorEntity>, +        context: &Context, +    ) -> Box<Future<Item = CreatorPostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "creator_post({:?}) - X-Span-ID: {:?}", +            body, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn editgroup_id_accept_post( +        &self, +        id: i32, +        context: &Context, +    ) -> Box<Future<Item = EditgroupIdAcceptPostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "editgroup_id_accept_post({}) - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn editgroup_id_get( +        &self, +        id: i32, +        context: &Context, +    ) -> Box<Future<Item = EditgroupIdGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "editgroup_id_get({}) - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn editgroup_post( +        &self, +        context: &Context, +    ) -> Box<Future<Item = EditgroupPostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "editgroup_post() - X-Span-ID: {:?}", +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn editor_username_changelog_get( +        &self, +        username: String, +        context: &Context, +    ) -> Box<Future<Item = EditorUsernameChangelogGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "editor_username_changelog_get(\"{}\") - X-Span-ID: {:?}", +            username, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn editor_username_get( +        &self, +        username: String, +        context: &Context, +    ) -> Box<Future<Item = EditorUsernameGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "editor_username_get(\"{}\") - X-Span-ID: {:?}", +            username, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn file_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = FileIdGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "file_id_get(\"{}\") - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn file_lookup_get( +        &self, +        sha1: String, +        context: &Context, +    ) -> Box<Future<Item = FileLookupGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "file_lookup_get(\"{}\") - X-Span-ID: {:?}", +            sha1, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn file_post( +        &self, +        body: Option<models::FileEntity>, +        context: &Context, +    ) -> Box<Future<Item = FilePostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "file_post({:?}) - X-Span-ID: {:?}", +            body, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn release_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = ReleaseIdGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "release_id_get(\"{}\") - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn release_lookup_get( +        &self, +        doi: String, +        context: &Context, +    ) -> Box<Future<Item = ReleaseLookupGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "release_lookup_get(\"{}\") - X-Span-ID: {:?}", +            doi, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn release_post( +        &self, +        body: Option<models::ReleaseEntity>, +        context: &Context, +    ) -> Box<Future<Item = ReleasePostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "release_post({:?}) - X-Span-ID: {:?}", +            body, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn work_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = WorkIdGetResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "work_id_get(\"{}\") - X-Span-ID: {:?}", +            id, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } + +    fn work_post( +        &self, +        body: Option<models::WorkEntity>, +        context: &Context, +    ) -> Box<Future<Item = WorkPostResponse, Error = ApiError>> { +        let context = context.clone(); +        println!( +            "work_post({:?}) - X-Span-ID: {:?}", +            body, +            context.x_span_id.unwrap_or(String::from("<none>")).clone() +        ); +        Box::new(futures::failed("Generic failure".into())) +    } +} diff --git a/rust/fatcat-api/src/client/mod.rs b/rust/fatcat-api/src/client/mod.rs new file mode 100644 index 00000000..361fd390 --- /dev/null +++ b/rust/fatcat-api/src/client/mod.rs @@ -0,0 +1,2573 @@ +#![allow(unused_extern_crates)] +extern crate chrono; +extern crate hyper_tls; +extern crate mime; +extern crate native_tls; +extern crate openssl; +extern crate tokio_core; +extern crate url; + +use self::tokio_core::reactor::Handle; +use self::url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; +use futures; +use futures::{Future, Stream}; +use futures::{future, stream}; +use hyper; +use hyper::Uri; +use hyper::header::{ContentType, Headers}; +use std::borrow::Cow; +use std::error; +use std::fmt; +use std::io::{Error, ErrorKind, Read}; +use std::path::Path; +use std::str; +use std::str::FromStr; +use std::sync::Arc; + +use mimetypes; + +use serde_json; + +#[allow(unused_imports)] +use std::collections::{BTreeMap, HashMap}; +#[allow(unused_imports)] +use swagger; + +use swagger::{ApiError, Context, XSpanId}; + +use models; +use {Api, ContainerIdGetResponse, ContainerLookupGetResponse, ContainerPostResponse, +     CreatorIdGetResponse, CreatorLookupGetResponse, CreatorPostResponse, +     EditgroupIdAcceptPostResponse, EditgroupIdGetResponse, EditgroupPostResponse, +     EditorUsernameChangelogGetResponse, EditorUsernameGetResponse, FileIdGetResponse, +     FileLookupGetResponse, FilePostResponse, ReleaseIdGetResponse, ReleaseLookupGetResponse, +     ReleasePostResponse, WorkIdGetResponse, WorkPostResponse}; + +/// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. +fn into_base_path( +    input: &str, +    correct_scheme: Option<&'static str>, +) -> Result<String, ClientInitError> { +    // First convert to Uri, since a base path is a subset of Uri. +    let uri = Uri::from_str(input)?; + +    let scheme = uri.scheme().ok_or(ClientInitError::InvalidScheme)?; + +    // Check the scheme if necessary +    if let Some(correct_scheme) = correct_scheme { +        if scheme != correct_scheme { +            return Err(ClientInitError::InvalidScheme); +        } +    } + +    let host = uri.host().ok_or_else(|| ClientInitError::MissingHost)?; +    let port = uri.port().map(|x| format!(":{}", x)).unwrap_or_default(); +    Ok(format!("{}://{}{}", scheme, host, port)) +} + +/// A client that implements the API by making HTTP calls out to a server. +#[derive(Clone)] +pub struct Client { +    hyper_client: Arc< +        Fn( +                &Handle +            ) -> Box< +                hyper::client::Service< +                    Request = hyper::Request<hyper::Body>, +                    Response = hyper::Response, +                    Error = hyper::Error, +                    Future = hyper::client::FutureResponse, +                >, +            > +            + Sync +            + Send, +    >, +    handle: Arc<Handle>, +    base_path: String, +} + +impl fmt::Debug for Client { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        write!(f, "Client {{ base_path: {} }}", self.base_path) +    } +} + +impl Client { +    /// Create an HTTP client. +    /// +    /// # Arguments +    /// * `handle` - tokio reactor handle to use for execution +    /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" +    pub fn try_new_http(handle: Handle, base_path: &str) -> Result<Client, ClientInitError> { +        let http_connector = swagger::http_connector(); +        Self::try_new_with_connector::<hyper::client::HttpConnector>( +            handle, +            base_path, +            Some("http"), +            http_connector, +        ) +    } + +    /// Create a client with a TLS connection to the server. +    /// +    /// # Arguments +    /// * `handle` - tokio reactor handle to use for execution +    /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" +    /// * `ca_certificate` - Path to CA certificate used to authenticate the server +    pub fn try_new_https<CA>( +        handle: Handle, +        base_path: &str, +        ca_certificate: CA, +    ) -> Result<Client, ClientInitError> +    where +        CA: AsRef<Path>, +    { +        let https_connector = swagger::https_connector(ca_certificate); +        Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>( +            handle, +            base_path, +            Some("https"), +            https_connector, +        ) +    } + +    /// Create a client with a mutually authenticated TLS connection to the server. +    /// +    /// # Arguments +    /// * `handle` - tokio reactor handle to use for execution +    /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" +    /// * `ca_certificate` - Path to CA certificate used to authenticate the server +    /// * `client_key` - Path to the client private key +    /// * `client_certificate` - Path to the client's public certificate associated with the private key +    pub fn try_new_https_mutual<CA, K, C, T>( +        handle: Handle, +        base_path: &str, +        ca_certificate: CA, +        client_key: K, +        client_certificate: C, +    ) -> Result<Client, ClientInitError> +    where +        CA: AsRef<Path>, +        K: AsRef<Path>, +        C: AsRef<Path>, +    { +        let https_connector = +            swagger::https_mutual_connector(ca_certificate, client_key, client_certificate); +        Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>( +            handle, +            base_path, +            Some("https"), +            https_connector, +        ) +    } + +    /// Create a client with a custom implementation of hyper::client::Connect. +    /// +    /// Intended for use with custom implementations of connect for e.g. protocol logging +    /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, +    /// this function should be used in conjunction with +    /// `swagger::{http_connector, https_connector, https_mutual_connector}`. +    /// +    /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` +    /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. +    /// +    /// # Arguments +    /// +    /// * `handle` - tokio reactor handle to use for execution +    /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" +    /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` +    /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` +    pub fn try_new_with_connector<C>( +        handle: Handle, +        base_path: &str, +        protocol: Option<&'static str>, +        connector_fn: Box<Fn(&Handle) -> C + Send + Sync>, +    ) -> Result<Client, ClientInitError> +    where +        C: hyper::client::Connect + hyper::client::Service, +    { +        let hyper_client = { +            move |handle: &Handle| -> Box< +                hyper::client::Service< +                    Request = hyper::Request<hyper::Body>, +                    Response = hyper::Response, +                    Error = hyper::Error, +                    Future = hyper::client::FutureResponse, +                >, +            > { +                let connector = connector_fn(handle); +                Box::new( +                    hyper::Client::configure() +                        .connector(connector) +                        .build(handle), +                ) +            } +        }; + +        Ok(Client { +            hyper_client: Arc::new(hyper_client), +            handle: Arc::new(handle), +            base_path: into_base_path(base_path, protocol)?, +        }) +    } + +    /// Constructor for creating a `Client` by passing in a pre-made `hyper` client. +    /// +    /// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport +    /// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of +    /// code generality, which may make it harder to move the application to a serverless environment, for example. +    /// +    /// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer. +    /// This is not a recommended way to write new tests. If other reasons are found for using this function, they +    /// should be mentioned here. +    pub fn try_new_with_hyper_client( +        hyper_client: Arc< +            Fn( +                    &Handle +                ) -> Box< +                    hyper::client::Service< +                        Request = hyper::Request<hyper::Body>, +                        Response = hyper::Response, +                        Error = hyper::Error, +                        Future = hyper::client::FutureResponse, +                    >, +                > +                + Sync +                + Send, +        >, +        handle: Handle, +        base_path: &str, +    ) -> Result<Client, ClientInitError> { +        Ok(Client { +            hyper_client: hyper_client, +            handle: Arc::new(handle), +            base_path: into_base_path(base_path, None)?, +        }) +    } +} + +impl Api for Client { +    fn container_id_get( +        &self, +        param_id: String, +        context: &Context, +    ) -> Box<Future<Item = ContainerIdGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/container/{id}", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::ContainerEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ContainerIdGetResponse::FetchASingleContainerById(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ContainerIdGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ContainerIdGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn container_lookup_get( +        &self, +        param_issn: String, +        context: &Context, +    ) -> Box<Future<Item = ContainerLookupGetResponse, Error = ApiError>> { +        // Query parameters +        let query_issn = format!("issn={issn}&", issn = param_issn.to_string()); + +        let uri = format!( +            "{}/v0/container/lookup?{issn}", +            self.base_path, +            issn = utf8_percent_encode(&query_issn, QUERY_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::ContainerEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ContainerLookupGetResponse::FindASingleContainerByExternalIdentifer(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ContainerLookupGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ContainerLookupGetResponse::NoSuchContainer(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ContainerLookupGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn container_post( +        &self, +        param_body: Option<models::ContainerEntity>, +        context: &Context, +    ) -> Box<Future<Item = ContainerPostResponse, Error = ApiError>> { +        let uri = format!("{}/v0/container", self.base_path); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        let body = param_body +            .map(|ref body| serde_json::to_string(body).expect("impossible to fail to serialize")); + +        if let Some(body) = body { +            request.set_body(body.into_bytes()); +        } + +        request +            .headers_mut() +            .set(ContentType(mimetypes::requests::CONTAINER_POST.clone())); +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    201 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::EntityEdit>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ContainerPostResponse::Created(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ContainerPostResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ContainerPostResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn creator_id_get( +        &self, +        param_id: String, +        context: &Context, +    ) -> Box<Future<Item = CreatorIdGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/creator/{id}", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::CreatorEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    CreatorIdGetResponse::FetchASingleCreatorById(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorIdGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorIdGetResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn creator_lookup_get( +        &self, +        param_orcid: String, +        context: &Context, +    ) -> Box<Future<Item = CreatorLookupGetResponse, Error = ApiError>> { +        // Query parameters +        let query_orcid = format!("orcid={orcid}&", orcid = param_orcid.to_string()); + +        let uri = format!( +            "{}/v0/creator/lookup?{orcid}", +            self.base_path, +            orcid = utf8_percent_encode(&query_orcid, QUERY_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::CreatorEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    CreatorLookupGetResponse::FindASingleCreatorByExternalIdentifer( +                                        body, +                                    ) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorLookupGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorLookupGetResponse::NoSuchCreator(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    CreatorLookupGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn creator_post( +        &self, +        param_body: Option<models::CreatorEntity>, +        context: &Context, +    ) -> Box<Future<Item = CreatorPostResponse, Error = ApiError>> { +        let uri = format!("{}/v0/creator", self.base_path); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        let body = param_body +            .map(|ref body| serde_json::to_string(body).expect("impossible to fail to serialize")); + +        if let Some(body) = body { +            request.set_body(body.into_bytes()); +        } + +        request +            .headers_mut() +            .set(ContentType(mimetypes::requests::CREATOR_POST.clone())); +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    201 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::EntityEdit>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorPostResponse::Created(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorPostResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| CreatorPostResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn editgroup_id_accept_post( +        &self, +        param_id: i32, +        context: &Context, +    ) -> Box<Future<Item = EditgroupIdAcceptPostResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/editgroup/{id}/accept", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Success>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupIdAcceptPostResponse::MergedEditgroupSuccessfully_( +                                        body, +                                    ) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupIdAcceptPostResponse::EditgroupIsInAnUnmergableState( +                                        body, +                                    ) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupIdAcceptPostResponse::NoSuchEditgroup(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupIdAcceptPostResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn editgroup_id_get( +        &self, +        param_id: i32, +        context: &Context, +    ) -> Box<Future<Item = EditgroupIdGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/editgroup/{id}", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Editgroup>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupIdGetResponse::FetchEditgroupByIdentifier(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| EditgroupIdGetResponse::NoSuchEditgroup(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupIdGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn editgroup_post( +        &self, +        context: &Context, +    ) -> Box<Future<Item = EditgroupPostResponse, Error = ApiError>> { +        let uri = format!("{}/v0/editgroup", self.base_path); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    201 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Editgroup>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| EditgroupPostResponse::SuccessfullyCreated(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditgroupPostResponse::InvalidRequestParameters(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| EditgroupPostResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn editor_username_changelog_get( +        &self, +        param_username: String, +        context: &Context, +    ) -> Box<Future<Item = EditorUsernameChangelogGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/editor/{username}/changelog", +            self.base_path, +            username = utf8_percent_encode(¶m_username.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Changelogentry>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditorUsernameChangelogGetResponse::FindChanges_(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditorUsernameChangelogGetResponse::UsernameNotFound(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditorUsernameChangelogGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn editor_username_get( +        &self, +        param_username: String, +        context: &Context, +    ) -> Box<Future<Item = EditorUsernameGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/editor/{username}", +            self.base_path, +            username = utf8_percent_encode(¶m_username.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Editor>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditorUsernameGetResponse::FetchGenericInformationAboutAnEditor( +                                        body, +                                    ) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| EditorUsernameGetResponse::UsernameNotFound(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    EditorUsernameGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn file_id_get( +        &self, +        param_id: String, +        context: &Context, +    ) -> Box<Future<Item = FileIdGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/file/{id}", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::FileEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FileIdGetResponse::FetchASingleFileById(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FileIdGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FileIdGetResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn file_lookup_get( +        &self, +        param_sha1: String, +        context: &Context, +    ) -> Box<Future<Item = FileLookupGetResponse, Error = ApiError>> { +        // Query parameters +        let query_sha1 = format!("sha1={sha1}&", sha1 = param_sha1.to_string()); + +        let uri = format!( +            "{}/v0/file/lookup?{sha1}", +            self.base_path, +            sha1 = utf8_percent_encode(&query_sha1, QUERY_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::FileEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    FileLookupGetResponse::FindASingleFileByExternalIdentifer(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FileLookupGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FileLookupGetResponse::NoSuchFile(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FileLookupGetResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn file_post( +        &self, +        param_body: Option<models::FileEntity>, +        context: &Context, +    ) -> Box<Future<Item = FilePostResponse, Error = ApiError>> { +        let uri = format!("{}/v0/file", self.base_path); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        let body = param_body +            .map(|ref body| serde_json::to_string(body).expect("impossible to fail to serialize")); + +        if let Some(body) = body { +            request.set_body(body.into_bytes()); +        } + +        request +            .headers_mut() +            .set(ContentType(mimetypes::requests::FILE_POST.clone())); +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    201 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::EntityEdit>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FilePostResponse::Created(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FilePostResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| FilePostResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn release_id_get( +        &self, +        param_id: String, +        context: &Context, +    ) -> Box<Future<Item = ReleaseIdGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/release/{id}", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::ReleaseEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ReleaseIdGetResponse::FetchASingleReleaseById(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleaseIdGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleaseIdGetResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn release_lookup_get( +        &self, +        param_doi: String, +        context: &Context, +    ) -> Box<Future<Item = ReleaseLookupGetResponse, Error = ApiError>> { +        // Query parameters +        let query_doi = format!("doi={doi}&", doi = param_doi.to_string()); + +        let uri = format!( +            "{}/v0/release/lookup?{doi}", +            self.base_path, +            doi = utf8_percent_encode(&query_doi, QUERY_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::ReleaseEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ReleaseLookupGetResponse::FindASingleReleaseByExternalIdentifer( +                                        body, +                                    ) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleaseLookupGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    404 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleaseLookupGetResponse::NoSuchRelease(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| { +                                    ReleaseLookupGetResponse::GenericErrorResponse(body) +                                }), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn release_post( +        &self, +        param_body: Option<models::ReleaseEntity>, +        context: &Context, +    ) -> Box<Future<Item = ReleasePostResponse, Error = ApiError>> { +        let uri = format!("{}/v0/release", self.base_path); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        let body = param_body +            .map(|ref body| serde_json::to_string(body).expect("impossible to fail to serialize")); + +        if let Some(body) = body { +            request.set_body(body.into_bytes()); +        } + +        request +            .headers_mut() +            .set(ContentType(mimetypes::requests::RELEASE_POST.clone())); +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    201 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::EntityEdit>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleasePostResponse::Created(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleasePostResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| ReleasePostResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn work_id_get( +        &self, +        param_id: String, +        context: &Context, +    ) -> Box<Future<Item = WorkIdGetResponse, Error = ApiError>> { +        let uri = format!( +            "{}/v0/work/{id}", +            self.base_path, +            id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET) +        ); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Get, uri); + +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    200 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::WorkEntity>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| WorkIdGetResponse::FetchASingleWorkById(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| WorkIdGetResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| WorkIdGetResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } + +    fn work_post( +        &self, +        param_body: Option<models::WorkEntity>, +        context: &Context, +    ) -> Box<Future<Item = WorkPostResponse, Error = ApiError>> { +        let uri = format!("{}/v0/work", self.base_path); + +        let uri = match Uri::from_str(&uri) { +            Ok(uri) => uri, +            Err(err) => { +                return Box::new(futures::done(Err(ApiError(format!( +                    "Unable to build URI: {}", +                    err +                ))))) +            } +        }; + +        let mut request = hyper::Request::new(hyper::Method::Post, uri); + +        let body = param_body +            .map(|ref body| serde_json::to_string(body).expect("impossible to fail to serialize")); + +        if let Some(body) = body { +            request.set_body(body.into_bytes()); +        } + +        request +            .headers_mut() +            .set(ContentType(mimetypes::requests::WORK_POST.clone())); +        context +            .x_span_id +            .as_ref() +            .map(|header| request.headers_mut().set(XSpanId(header.clone()))); + +        let hyper_client = (self.hyper_client)(&*self.handle); +        Box::new( +            hyper_client +                .call(request) +                .map_err(|e| ApiError(format!("No response received: {}", e))) +                .and_then(|mut response| match response.status().as_u16() { +                    201 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::EntityEdit>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| WorkPostResponse::Created(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    400 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| WorkPostResponse::BadRequest(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    0 => { +                        let body = response.body(); +                        Box::new( +                            body.concat2() +                                .map_err(|e| ApiError(format!("Failed to read response: {}", e))) +                                .and_then(|body| { +                                    str::from_utf8(&body) +                                        .map_err(|e| { +                                            ApiError(format!("Response was not valid UTF8: {}", e)) +                                        }) +                                        .and_then(|body| { +                                            serde_json::from_str::<models::Error>(body) +                                                .map_err(|e| e.into()) +                                        }) +                                }) +                                .map(move |body| WorkPostResponse::GenericErrorResponse(body)), +                        ) as Box<Future<Item = _, Error = _>> +                    } +                    code => { +                        let headers = response.headers().clone(); +                        Box::new(response.body().take(100).concat2().then(move |body| { +                            future::err(ApiError(format!( +                                "Unexpected response code {}:\n{:?}\n\n{}", +                                code, +                                headers, +                                match body { +                                    Ok(ref body) => match str::from_utf8(body) { +                                        Ok(body) => Cow::from(body), +                                        Err(e) => { +                                            Cow::from(format!("<Body was not UTF8: {:?}>", e)) +                                        } +                                    }, +                                    Err(e) => Cow::from(format!("<Failed to read body: {}>", e)), +                                } +                            ))) +                        })) as Box<Future<Item = _, Error = _>> +                    } +                }), +        ) +    } +} + +#[derive(Debug)] +pub enum ClientInitError { +    InvalidScheme, +    InvalidUri(hyper::error::UriError), +    MissingHost, +    SslError(openssl::error::ErrorStack), +} + +impl From<hyper::error::UriError> for ClientInitError { +    fn from(err: hyper::error::UriError) -> ClientInitError { +        ClientInitError::InvalidUri(err) +    } +} + +impl From<openssl::error::ErrorStack> for ClientInitError { +    fn from(err: openssl::error::ErrorStack) -> ClientInitError { +        ClientInitError::SslError(err) +    } +} + +impl fmt::Display for ClientInitError { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        (self as &fmt::Debug).fmt(f) +    } +} + +impl error::Error for ClientInitError { +    fn description(&self) -> &str { +        "Failed to produce a hyper client." +    } +} diff --git a/rust/fatcat-api/src/lib.rs b/rust/fatcat-api/src/lib.rs new file mode 100644 index 00000000..36573537 --- /dev/null +++ b/rust/fatcat-api/src/lib.rs @@ -0,0 +1,599 @@ +#![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 chrono; +extern crate futures; +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; + +// 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; + +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; + +pub use swagger::{ApiError, Context, ContextWrapper}; + +pub const BASE_PATH: &'static str = "/v0"; +pub const API_VERSION: &'static str = "0.1.0"; + +#[derive(Debug, PartialEq)] +pub enum ContainerIdGetResponse { +    /// fetch a single container by id +    FetchASingleContainerById(models::ContainerEntity), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum ContainerLookupGetResponse { +    /// find a single container by external identifer +    FindASingleContainerByExternalIdentifer(models::ContainerEntity), +    /// bad request +    BadRequest(models::Error), +    /// no such container +    NoSuchContainer(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum ContainerPostResponse { +    /// created +    Created(models::EntityEdit), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum CreatorIdGetResponse { +    /// fetch a single creator by id +    FetchASingleCreatorById(models::CreatorEntity), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum CreatorLookupGetResponse { +    /// find a single creator by external identifer +    FindASingleCreatorByExternalIdentifer(models::CreatorEntity), +    /// bad request +    BadRequest(models::Error), +    /// no such creator +    NoSuchCreator(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum CreatorPostResponse { +    /// created +    Created(models::EntityEdit), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum EditgroupIdAcceptPostResponse { +    /// merged editgroup successfully (\"live\") +    MergedEditgroupSuccessfully_(models::Success), +    /// editgroup is in an unmergable state +    EditgroupIsInAnUnmergableState(models::Error), +    /// no such editgroup +    NoSuchEditgroup(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum EditgroupIdGetResponse { +    /// fetch editgroup by identifier +    FetchEditgroupByIdentifier(models::Editgroup), +    /// no such editgroup +    NoSuchEditgroup(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum EditgroupPostResponse { +    /// successfully created +    SuccessfullyCreated(models::Editgroup), +    /// invalid request parameters +    InvalidRequestParameters(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum EditorUsernameChangelogGetResponse { +    /// find changes (editgroups) by this editor which have been merged +    FindChanges_(models::Changelogentry), +    /// username not found +    UsernameNotFound(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum EditorUsernameGetResponse { +    /// fetch generic information about an editor +    FetchGenericInformationAboutAnEditor(models::Editor), +    /// username not found +    UsernameNotFound(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum FileIdGetResponse { +    /// fetch a single file by id +    FetchASingleFileById(models::FileEntity), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum FileLookupGetResponse { +    /// find a single file by external identifer +    FindASingleFileByExternalIdentifer(models::FileEntity), +    /// bad request +    BadRequest(models::Error), +    /// no such file +    NoSuchFile(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum FilePostResponse { +    /// created +    Created(models::EntityEdit), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum ReleaseIdGetResponse { +    /// fetch a single release by id +    FetchASingleReleaseById(models::ReleaseEntity), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum ReleaseLookupGetResponse { +    /// find a single release by external identifer +    FindASingleReleaseByExternalIdentifer(models::ReleaseEntity), +    /// bad request +    BadRequest(models::Error), +    /// no such release +    NoSuchRelease(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum ReleasePostResponse { +    /// created +    Created(models::EntityEdit), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum WorkIdGetResponse { +    /// fetch a single work by id +    FetchASingleWorkById(models::WorkEntity), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +#[derive(Debug, PartialEq)] +pub enum WorkPostResponse { +    /// created +    Created(models::EntityEdit), +    /// bad request +    BadRequest(models::Error), +    /// generic error response +    GenericErrorResponse(models::Error), +} + +/// API +pub trait Api { +    fn container_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = ContainerIdGetResponse, Error = ApiError>>; + +    fn container_lookup_get( +        &self, +        issn: String, +        context: &Context, +    ) -> Box<Future<Item = ContainerLookupGetResponse, Error = ApiError>>; + +    fn container_post( +        &self, +        body: Option<models::ContainerEntity>, +        context: &Context, +    ) -> Box<Future<Item = ContainerPostResponse, Error = ApiError>>; + +    fn creator_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = CreatorIdGetResponse, Error = ApiError>>; + +    fn creator_lookup_get( +        &self, +        orcid: String, +        context: &Context, +    ) -> Box<Future<Item = CreatorLookupGetResponse, Error = ApiError>>; + +    fn creator_post( +        &self, +        body: Option<models::CreatorEntity>, +        context: &Context, +    ) -> Box<Future<Item = CreatorPostResponse, Error = ApiError>>; + +    fn editgroup_id_accept_post( +        &self, +        id: i32, +        context: &Context, +    ) -> Box<Future<Item = EditgroupIdAcceptPostResponse, Error = ApiError>>; + +    fn editgroup_id_get( +        &self, +        id: i32, +        context: &Context, +    ) -> Box<Future<Item = EditgroupIdGetResponse, Error = ApiError>>; + +    fn editgroup_post( +        &self, +        context: &Context, +    ) -> Box<Future<Item = EditgroupPostResponse, Error = ApiError>>; + +    fn editor_username_changelog_get( +        &self, +        username: String, +        context: &Context, +    ) -> Box<Future<Item = EditorUsernameChangelogGetResponse, Error = ApiError>>; + +    fn editor_username_get( +        &self, +        username: String, +        context: &Context, +    ) -> Box<Future<Item = EditorUsernameGetResponse, Error = ApiError>>; + +    fn file_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = FileIdGetResponse, Error = ApiError>>; + +    fn file_lookup_get( +        &self, +        sha1: String, +        context: &Context, +    ) -> Box<Future<Item = FileLookupGetResponse, Error = ApiError>>; + +    fn file_post( +        &self, +        body: Option<models::FileEntity>, +        context: &Context, +    ) -> Box<Future<Item = FilePostResponse, Error = ApiError>>; + +    fn release_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = ReleaseIdGetResponse, Error = ApiError>>; + +    fn release_lookup_get( +        &self, +        doi: String, +        context: &Context, +    ) -> Box<Future<Item = ReleaseLookupGetResponse, Error = ApiError>>; + +    fn release_post( +        &self, +        body: Option<models::ReleaseEntity>, +        context: &Context, +    ) -> Box<Future<Item = ReleasePostResponse, Error = ApiError>>; + +    fn work_id_get( +        &self, +        id: String, +        context: &Context, +    ) -> Box<Future<Item = WorkIdGetResponse, Error = ApiError>>; + +    fn work_post( +        &self, +        body: Option<models::WorkEntity>, +        context: &Context, +    ) -> Box<Future<Item = WorkPostResponse, Error = ApiError>>; +} + +/// API without a `Context` +pub trait ApiNoContext { +    fn container_id_get( +        &self, +        id: String, +    ) -> Box<Future<Item = ContainerIdGetResponse, Error = ApiError>>; + +    fn container_lookup_get( +        &self, +        issn: String, +    ) -> Box<Future<Item = ContainerLookupGetResponse, Error = ApiError>>; + +    fn container_post( +        &self, +        body: Option<models::ContainerEntity>, +    ) -> Box<Future<Item = ContainerPostResponse, Error = ApiError>>; + +    fn creator_id_get( +        &self, +        id: String, +    ) -> Box<Future<Item = CreatorIdGetResponse, Error = ApiError>>; + +    fn creator_lookup_get( +        &self, +        orcid: String, +    ) -> Box<Future<Item = CreatorLookupGetResponse, Error = ApiError>>; + +    fn creator_post( +        &self, +        body: Option<models::CreatorEntity>, +    ) -> Box<Future<Item = CreatorPostResponse, Error = ApiError>>; + +    fn editgroup_id_accept_post( +        &self, +        id: i32, +    ) -> Box<Future<Item = EditgroupIdAcceptPostResponse, Error = ApiError>>; + +    fn editgroup_id_get( +        &self, +        id: i32, +    ) -> Box<Future<Item = EditgroupIdGetResponse, Error = ApiError>>; + +    fn editgroup_post(&self) -> Box<Future<Item = EditgroupPostResponse, Error = ApiError>>; + +    fn editor_username_changelog_get( +        &self, +        username: String, +    ) -> Box<Future<Item = EditorUsernameChangelogGetResponse, Error = ApiError>>; + +    fn editor_username_get( +        &self, +        username: String, +    ) -> Box<Future<Item = EditorUsernameGetResponse, Error = ApiError>>; + +    fn file_id_get(&self, id: String) -> Box<Future<Item = FileIdGetResponse, Error = ApiError>>; + +    fn file_lookup_get( +        &self, +        sha1: String, +    ) -> Box<Future<Item = FileLookupGetResponse, Error = ApiError>>; + +    fn file_post( +        &self, +        body: Option<models::FileEntity>, +    ) -> Box<Future<Item = FilePostResponse, Error = ApiError>>; + +    fn release_id_get( +        &self, +        id: String, +    ) -> Box<Future<Item = ReleaseIdGetResponse, Error = ApiError>>; + +    fn release_lookup_get( +        &self, +        doi: String, +    ) -> Box<Future<Item = ReleaseLookupGetResponse, Error = ApiError>>; + +    fn release_post( +        &self, +        body: Option<models::ReleaseEntity>, +    ) -> Box<Future<Item = ReleasePostResponse, Error = ApiError>>; + +    fn work_id_get(&self, id: String) -> Box<Future<Item = WorkIdGetResponse, Error = ApiError>>; + +    fn work_post( +        &self, +        body: Option<models::WorkEntity>, +    ) -> Box<Future<Item = WorkPostResponse, Error = ApiError>>; +} + +/// Trait to extend an API to make it easy to bind it to a context. +pub trait ContextWrapperExt<'a> +where +    Self: Sized, +{ +    /// Binds this API to a context. +    fn with_context(self: &'a Self, context: Context) -> ContextWrapper<'a, Self>; +} + +impl<'a, T: Api + Sized> ContextWrapperExt<'a> for T { +    fn with_context(self: &'a T, context: Context) -> ContextWrapper<'a, T> { +        ContextWrapper::<T>::new(self, context) +    } +} + +impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { +    fn container_id_get( +        &self, +        id: String, +    ) -> Box<Future<Item = ContainerIdGetResponse, Error = ApiError>> { +        self.api().container_id_get(id, &self.context()) +    } + +    fn container_lookup_get( +        &self, +        issn: String, +    ) -> Box<Future<Item = ContainerLookupGetResponse, Error = ApiError>> { +        self.api().container_lookup_get(issn, &self.context()) +    } + +    fn container_post( +        &self, +        body: Option<models::ContainerEntity>, +    ) -> Box<Future<Item = ContainerPostResponse, Error = ApiError>> { +        self.api().container_post(body, &self.context()) +    } + +    fn creator_id_get( +        &self, +        id: String, +    ) -> Box<Future<Item = CreatorIdGetResponse, Error = ApiError>> { +        self.api().creator_id_get(id, &self.context()) +    } + +    fn creator_lookup_get( +        &self, +        orcid: String, +    ) -> Box<Future<Item = CreatorLookupGetResponse, Error = ApiError>> { +        self.api().creator_lookup_get(orcid, &self.context()) +    } + +    fn creator_post( +        &self, +        body: Option<models::CreatorEntity>, +    ) -> Box<Future<Item = CreatorPostResponse, Error = ApiError>> { +        self.api().creator_post(body, &self.context()) +    } + +    fn editgroup_id_accept_post( +        &self, +        id: i32, +    ) -> Box<Future<Item = EditgroupIdAcceptPostResponse, Error = ApiError>> { +        self.api().editgroup_id_accept_post(id, &self.context()) +    } + +    fn editgroup_id_get( +        &self, +        id: i32, +    ) -> Box<Future<Item = EditgroupIdGetResponse, Error = ApiError>> { +        self.api().editgroup_id_get(id, &self.context()) +    } + +    fn editgroup_post(&self) -> Box<Future<Item = EditgroupPostResponse, Error = ApiError>> { +        self.api().editgroup_post(&self.context()) +    } + +    fn editor_username_changelog_get( +        &self, +        username: String, +    ) -> Box<Future<Item = EditorUsernameChangelogGetResponse, Error = ApiError>> { +        self.api() +            .editor_username_changelog_get(username, &self.context()) +    } + +    fn editor_username_get( +        &self, +        username: String, +    ) -> Box<Future<Item = EditorUsernameGetResponse, Error = ApiError>> { +        self.api().editor_username_get(username, &self.context()) +    } + +    fn file_id_get(&self, id: String) -> Box<Future<Item = FileIdGetResponse, Error = ApiError>> { +        self.api().file_id_get(id, &self.context()) +    } + +    fn file_lookup_get( +        &self, +        sha1: String, +    ) -> Box<Future<Item = FileLookupGetResponse, Error = ApiError>> { +        self.api().file_lookup_get(sha1, &self.context()) +    } + +    fn file_post( +        &self, +        body: Option<models::FileEntity>, +    ) -> Box<Future<Item = FilePostResponse, Error = ApiError>> { +        self.api().file_post(body, &self.context()) +    } + +    fn release_id_get( +        &self, +        id: String, +    ) -> Box<Future<Item = ReleaseIdGetResponse, Error = ApiError>> { +        self.api().release_id_get(id, &self.context()) +    } + +    fn release_lookup_get( +        &self, +        doi: String, +    ) -> Box<Future<Item = ReleaseLookupGetResponse, Error = ApiError>> { +        self.api().release_lookup_get(doi, &self.context()) +    } + +    fn release_post( +        &self, +        body: Option<models::ReleaseEntity>, +    ) -> Box<Future<Item = ReleasePostResponse, Error = ApiError>> { +        self.api().release_post(body, &self.context()) +    } + +    fn work_id_get(&self, id: String) -> Box<Future<Item = WorkIdGetResponse, Error = ApiError>> { +        self.api().work_id_get(id, &self.context()) +    } + +    fn work_post( +        &self, +        body: Option<models::WorkEntity>, +    ) -> Box<Future<Item = WorkPostResponse, Error = ApiError>> { +        self.api().work_post(body, &self.context()) +    } +} + +#[cfg(feature = "client")] +pub mod client; + +// Re-export Client as a top-level name +#[cfg(feature = "client")] +pub use self::client::Client; + +#[cfg(feature = "server")] +pub mod server; + +// Re-export router() as a top-level name +#[cfg(feature = "server")] +pub use self::server::Service; + +pub mod models; diff --git a/rust/fatcat-api/src/mimetypes.rs b/rust/fatcat-api/src/mimetypes.rs new file mode 100644 index 00000000..dfbff890 --- /dev/null +++ b/rust/fatcat-api/src/mimetypes.rs @@ -0,0 +1,313 @@ +/// mime types for requests and responses + +pub mod responses { +    use hyper::mime::*; + +    // The macro is called per-operation to beat the recursion limit +    /// Create Mime objects for the response content types for ContainerIdGet +    lazy_static! { +        pub static ref CONTAINER_ID_GET_FETCH_A_SINGLE_CONTAINER_BY_ID: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerIdGet +    lazy_static! { +        pub static ref CONTAINER_ID_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerIdGet +    lazy_static! { +        pub static ref CONTAINER_ID_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerLookupGet +    lazy_static! { +        pub static ref CONTAINER_LOOKUP_GET_FIND_A_SINGLE_CONTAINER_BY_EXTERNAL_IDENTIFER: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerLookupGet +    lazy_static! { +        pub static ref CONTAINER_LOOKUP_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerLookupGet +    lazy_static! { +        pub static ref CONTAINER_LOOKUP_GET_NO_SUCH_CONTAINER: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerLookupGet +    lazy_static! { +        pub static ref CONTAINER_LOOKUP_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerPost +    lazy_static! { +        pub static ref CONTAINER_POST_CREATED: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerPost +    lazy_static! { +        pub static ref CONTAINER_POST_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ContainerPost +    lazy_static! { +        pub static ref CONTAINER_POST_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorIdGet +    lazy_static! { +        pub static ref CREATOR_ID_GET_FETCH_A_SINGLE_CREATOR_BY_ID: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorIdGet +    lazy_static! { +        pub static ref CREATOR_ID_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorIdGet +    lazy_static! { +        pub static ref CREATOR_ID_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorLookupGet +    lazy_static! { +        pub static ref CREATOR_LOOKUP_GET_FIND_A_SINGLE_CREATOR_BY_EXTERNAL_IDENTIFER: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorLookupGet +    lazy_static! { +        pub static ref CREATOR_LOOKUP_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorLookupGet +    lazy_static! { +        pub static ref CREATOR_LOOKUP_GET_NO_SUCH_CREATOR: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorLookupGet +    lazy_static! { +        pub static ref CREATOR_LOOKUP_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorPost +    lazy_static! { +        pub static ref CREATOR_POST_CREATED: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorPost +    lazy_static! { +        pub static ref CREATOR_POST_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for CreatorPost +    lazy_static! { +        pub static ref CREATOR_POST_GENERIC_ERROR_RESPONSE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdAcceptPost +    lazy_static! { +        pub static ref EDITGROUP_ID_ACCEPT_POST_MERGED_EDITGROUP_SUCCESSFULLY_: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdAcceptPost +    lazy_static! { +        pub static ref EDITGROUP_ID_ACCEPT_POST_EDITGROUP_IS_IN_AN_UNMERGABLE_STATE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdAcceptPost +    lazy_static! { +        pub static ref EDITGROUP_ID_ACCEPT_POST_NO_SUCH_EDITGROUP: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdAcceptPost +    lazy_static! { +        pub static ref EDITGROUP_ID_ACCEPT_POST_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdGet +    lazy_static! { +        pub static ref EDITGROUP_ID_GET_FETCH_EDITGROUP_BY_IDENTIFIER: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdGet +    lazy_static! { +        pub static ref EDITGROUP_ID_GET_NO_SUCH_EDITGROUP: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupIdGet +    lazy_static! { +        pub static ref EDITGROUP_ID_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupPost +    lazy_static! { +        pub static ref EDITGROUP_POST_SUCCESSFULLY_CREATED: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupPost +    lazy_static! { +        pub static ref EDITGROUP_POST_INVALID_REQUEST_PARAMETERS: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditgroupPost +    lazy_static! { +        pub static ref EDITGROUP_POST_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditorUsernameChangelogGet +    lazy_static! { +        pub static ref EDITOR_USERNAME_CHANGELOG_GET_FIND_CHANGES_: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditorUsernameChangelogGet +    lazy_static! { +        pub static ref EDITOR_USERNAME_CHANGELOG_GET_USERNAME_NOT_FOUND: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditorUsernameChangelogGet +    lazy_static! { +        pub static ref EDITOR_USERNAME_CHANGELOG_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditorUsernameGet +    lazy_static! { +        pub static ref EDITOR_USERNAME_GET_FETCH_GENERIC_INFORMATION_ABOUT_AN_EDITOR: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditorUsernameGet +    lazy_static! { +        pub static ref EDITOR_USERNAME_GET_USERNAME_NOT_FOUND: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for EditorUsernameGet +    lazy_static! { +        pub static ref EDITOR_USERNAME_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileIdGet +    lazy_static! { +        pub static ref FILE_ID_GET_FETCH_A_SINGLE_FILE_BY_ID: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileIdGet +    lazy_static! { +        pub static ref FILE_ID_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileIdGet +    lazy_static! { +        pub static ref FILE_ID_GET_GENERIC_ERROR_RESPONSE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileLookupGet +    lazy_static! { +        pub static ref FILE_LOOKUP_GET_FIND_A_SINGLE_FILE_BY_EXTERNAL_IDENTIFER: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileLookupGet +    lazy_static! { +        pub static ref FILE_LOOKUP_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileLookupGet +    lazy_static! { +        pub static ref FILE_LOOKUP_GET_NO_SUCH_FILE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FileLookupGet +    lazy_static! { +        pub static ref FILE_LOOKUP_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FilePost +    lazy_static! { +        pub static ref FILE_POST_CREATED: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FilePost +    lazy_static! { +        pub static ref FILE_POST_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for FilePost +    lazy_static! { +        pub static ref FILE_POST_GENERIC_ERROR_RESPONSE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseIdGet +    lazy_static! { +        pub static ref RELEASE_ID_GET_FETCH_A_SINGLE_RELEASE_BY_ID: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseIdGet +    lazy_static! { +        pub static ref RELEASE_ID_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseIdGet +    lazy_static! { +        pub static ref RELEASE_ID_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseLookupGet +    lazy_static! { +        pub static ref RELEASE_LOOKUP_GET_FIND_A_SINGLE_RELEASE_BY_EXTERNAL_IDENTIFER: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseLookupGet +    lazy_static! { +        pub static ref RELEASE_LOOKUP_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseLookupGet +    lazy_static! { +        pub static ref RELEASE_LOOKUP_GET_NO_SUCH_RELEASE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleaseLookupGet +    lazy_static! { +        pub static ref RELEASE_LOOKUP_GET_GENERIC_ERROR_RESPONSE: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleasePost +    lazy_static! { +        pub static ref RELEASE_POST_CREATED: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleasePost +    lazy_static! { +        pub static ref RELEASE_POST_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for ReleasePost +    lazy_static! { +        pub static ref RELEASE_POST_GENERIC_ERROR_RESPONSE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for WorkIdGet +    lazy_static! { +        pub static ref WORK_ID_GET_FETCH_A_SINGLE_WORK_BY_ID: Mime = +            "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for WorkIdGet +    lazy_static! { +        pub static ref WORK_ID_GET_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for WorkIdGet +    lazy_static! { +        pub static ref WORK_ID_GET_GENERIC_ERROR_RESPONSE: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for WorkPost +    lazy_static! { +        pub static ref WORK_POST_CREATED: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for WorkPost +    lazy_static! { +        pub static ref WORK_POST_BAD_REQUEST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the response content types for WorkPost +    lazy_static! { +        pub static ref WORK_POST_GENERIC_ERROR_RESPONSE: Mime = "application/json".parse().unwrap(); +    } + +} + +pub mod requests { +    use hyper::mime::*; +    /// Create Mime objects for the request content types for ContainerPost +    lazy_static! { +        pub static ref CONTAINER_POST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the request content types for CreatorPost +    lazy_static! { +        pub static ref CREATOR_POST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the request content types for FilePost +    lazy_static! { +        pub static ref FILE_POST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the request content types for ReleasePost +    lazy_static! { +        pub static ref RELEASE_POST: Mime = "application/json".parse().unwrap(); +    } +    /// Create Mime objects for the request content types for WorkPost +    lazy_static! { +        pub static ref WORK_POST: Mime = "application/json".parse().unwrap(); +    } + +} diff --git a/rust/fatcat-api/src/models.rs b/rust/fatcat-api/src/models.rs new file mode 100644 index 00000000..3d104b78 --- /dev/null +++ b/rust/fatcat-api/src/models.rs @@ -0,0 +1,392 @@ +#![allow(unused_imports, unused_qualifications, unused_extern_crates)] +extern crate chrono; +extern crate uuid; + +use serde::ser::Serializer; + +use models; +use std::collections::HashMap; +use swagger; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Changelogentry { +    #[serde(rename = "index")] +    pub index: isize, + +    #[serde(rename = "editgroup_id")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup_id: Option<isize>, + +    #[serde(rename = "timestamp")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub timestamp: Option<chrono::DateTime<chrono::Utc>>, +} + +impl Changelogentry { +    pub fn new(index: isize) -> Changelogentry { +        Changelogentry { +            index: index, +            editgroup_id: None, +            timestamp: None, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ContainerEntity { +    #[serde(rename = "issn")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub issn: Option<String>, + +    #[serde(rename = "publisher")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub publisher: Option<String>, + +    #[serde(rename = "parent")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub parent: Option<String>, + +    #[serde(rename = "name")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub name: Option<String>, + +    // Note: inline enums are not fully supported by swagger-codegen +    #[serde(rename = "state")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub state: Option<String>, + +    #[serde(rename = "ident")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub ident: Option<String>, + +    #[serde(rename = "revision")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub revision: Option<isize>, + +    #[serde(rename = "redirect")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub redirect: Option<String>, + +    #[serde(rename = "editgroup")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup: Option<isize>, +} + +impl ContainerEntity { +    pub fn new() -> ContainerEntity { +        ContainerEntity { +            issn: None, +            publisher: None, +            parent: None, +            name: None, +            state: None, +            ident: None, +            revision: None, +            redirect: None, +            editgroup: None, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct CreatorEntity { +    #[serde(rename = "orcid")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub orcid: Option<String>, + +    #[serde(rename = "name")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub name: Option<String>, + +    #[serde(rename = "editgroup")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup: Option<isize>, + +    #[serde(rename = "redirect")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub redirect: Option<String>, + +    #[serde(rename = "revision")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub revision: Option<isize>, + +    #[serde(rename = "ident")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub ident: Option<String>, + +    // Note: inline enums are not fully supported by swagger-codegen +    #[serde(rename = "state")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub state: Option<String>, +} + +impl CreatorEntity { +    pub fn new() -> CreatorEntity { +        CreatorEntity { +            orcid: None, +            name: None, +            editgroup: None, +            redirect: None, +            revision: None, +            ident: None, +            state: None, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Editgroup { +    #[serde(rename = "id")] +    pub id: isize, + +    #[serde(rename = "editor_id")] +    pub editor_id: isize, +} + +impl Editgroup { +    pub fn new(id: isize, editor_id: isize) -> Editgroup { +        Editgroup { +            id: id, +            editor_id: editor_id, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Editor { +    #[serde(rename = "username")] +    pub username: String, +} + +impl Editor { +    pub fn new(username: String) -> Editor { +        Editor { username: username } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct EntityEdit { +    #[serde(rename = "editgroup_id")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup_id: Option<isize>, + +    #[serde(rename = "revision")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub revision: Option<isize>, + +    #[serde(rename = "ident")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub ident: Option<String>, + +    #[serde(rename = "id")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub id: Option<isize>, +} + +impl EntityEdit { +    pub fn new() -> EntityEdit { +        EntityEdit { +            editgroup_id: None, +            revision: None, +            ident: None, +            id: None, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Error { +    #[serde(rename = "message")] +    pub message: String, +} + +impl Error { +    pub fn new(message: String) -> Error { +        Error { message: message } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct FileEntity { +    #[serde(rename = "url")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub url: Option<String>, + +    #[serde(rename = "sha1")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub sha1: Option<String>, + +    #[serde(rename = "size")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub size: Option<isize>, + +    #[serde(rename = "editgroup")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup: Option<isize>, + +    #[serde(rename = "redirect")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub redirect: Option<String>, + +    #[serde(rename = "revision")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub revision: Option<isize>, + +    #[serde(rename = "ident")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub ident: Option<String>, + +    // Note: inline enums are not fully supported by swagger-codegen +    #[serde(rename = "state")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub state: Option<String>, +} + +impl FileEntity { +    pub fn new() -> FileEntity { +        FileEntity { +            url: None, +            sha1: None, +            size: None, +            editgroup: None, +            redirect: None, +            revision: None, +            ident: None, +            state: None, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ReleaseEntity { +    #[serde(rename = "issue")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub issue: Option<String>, + +    #[serde(rename = "pages")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub pages: Option<String>, + +    #[serde(rename = "volume")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub volume: Option<String>, + +    #[serde(rename = "doi")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub doi: Option<String>, + +    #[serde(rename = "release_type")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub release_type: Option<String>, + +    #[serde(rename = "license")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub license: Option<String>, + +    #[serde(rename = "container")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub container: Option<String>, + +    #[serde(rename = "work")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub work: Option<String>, + +    // Note: inline enums are not fully supported by swagger-codegen +    #[serde(rename = "state")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub state: Option<String>, + +    #[serde(rename = "ident")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub ident: Option<String>, + +    #[serde(rename = "revision")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub revision: Option<isize>, + +    #[serde(rename = "redirect")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub redirect: Option<String>, + +    #[serde(rename = "editgroup")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup: Option<isize>, +} + +impl ReleaseEntity { +    pub fn new() -> ReleaseEntity { +        ReleaseEntity { +            issue: None, +            pages: None, +            volume: None, +            doi: None, +            release_type: None, +            license: None, +            container: None, +            work: None, +            state: None, +            ident: None, +            revision: None, +            redirect: None, +            editgroup: None, +        } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Success { +    #[serde(rename = "message")] +    pub message: String, +} + +impl Success { +    pub fn new(message: String) -> Success { +        Success { message: message } +    } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct WorkEntity { +    #[serde(rename = "work_type")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub work_type: Option<String>, + +    #[serde(rename = "title")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub title: Option<String>, + +    #[serde(rename = "editgroup")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub editgroup: Option<isize>, + +    #[serde(rename = "redirect")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub redirect: Option<String>, + +    #[serde(rename = "revision")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub revision: Option<isize>, + +    #[serde(rename = "ident")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub ident: Option<String>, + +    // Note: inline enums are not fully supported by swagger-codegen +    #[serde(rename = "state")] +    #[serde(skip_serializing_if = "Option::is_none")] +    pub state: Option<String>, +} + +impl WorkEntity { +    pub fn new() -> WorkEntity { +        WorkEntity { +            work_type: None, +            title: None, +            editgroup: None, +            redirect: None, +            revision: None, +            ident: None, +            state: None, +        } +    } +} diff --git a/rust/fatcat-api/src/server/auth.rs b/rust/fatcat-api/src/server/auth.rs new file mode 100644 index 00000000..48dfd7d6 --- /dev/null +++ b/rust/fatcat-api/src/server/auth.rs @@ -0,0 +1,93 @@ +use Api; +use hyper; +use hyper::{Error, Request, Response, StatusCode}; +use server::url::form_urlencoded; +use std::io; +use swagger::auth::{AuthData, Authorization, Scopes}; + +pub struct NewService<T> +where +    T: hyper::server::NewService< +        Request = (Request, Option<AuthData>), +        Response = Response, +        Error = Error, +    >, +{ +    inner: T, +} + +impl<T> NewService<T> +where +    T: hyper::server::NewService< +            Request = (Request, Option<AuthData>), +            Response = Response, +            Error = Error, +        > +        + 'static, +{ +    pub fn new(inner: T) -> NewService<T> { +        NewService { inner } +    } +} + +impl<T> hyper::server::NewService for NewService<T> +where +    T: hyper::server::NewService< +            Request = (Request, Option<AuthData>), +            Response = Response, +            Error = Error, +        > +        + 'static, +{ +    type Request = Request; +    type Response = Response; +    type Error = Error; +    type Instance = Service<T::Instance>; + +    fn new_service(&self) -> Result<Self::Instance, io::Error> { +        self.inner.new_service().map(|s| Service::new(s)) +    } +} + +/// Middleware to extract authentication data from request +pub struct Service<T> +where +    T: hyper::server::Service< +        Request = (Request, Option<AuthData>), +        Response = Response, +        Error = Error, +    >, +{ +    inner: T, +} + +impl<T> Service<T> +where +    T: hyper::server::Service< +        Request = (Request, Option<AuthData>), +        Response = Response, +        Error = Error, +    >, +{ +    pub fn new(inner: T) -> Service<T> { +        Service { inner } +    } +} + +impl<T> hyper::server::Service for Service<T> +where +    T: hyper::server::Service< +        Request = (Request, Option<AuthData>), +        Response = Response, +        Error = Error, +    >, +{ +    type Request = Request; +    type Response = Response; +    type Error = Error; +    type Future = T::Future; + +    fn call(&self, req: Self::Request) -> Self::Future { +        return self.inner.call((req, None)); +    } +} diff --git a/rust/fatcat-api/src/server/mod.rs b/rust/fatcat-api/src/server/mod.rs new file mode 100644 index 00000000..186f8272 --- /dev/null +++ b/rust/fatcat-api/src/server/mod.rs @@ -0,0 +1,2485 @@ +#![allow(unused_extern_crates)] +extern crate chrono; +extern crate hyper_tls; +extern crate mime; +extern crate native_tls; +extern crate openssl; +extern crate serde_ignored; +extern crate tokio_core; +extern crate uuid; + +extern crate percent_encoding; +extern crate url; + +use self::url::form_urlencoded; +use futures::{future, stream, Future, Stream}; +use hyper; +use hyper::header::{ContentType, Headers}; +use hyper::{Error, Request, Response, StatusCode}; +use mimetypes; +use std::sync::Arc; + +use serde_json; + +#[allow(unused_imports)] +use std::collections::{BTreeMap, HashMap}; +use std::io; +#[allow(unused_imports)] +use swagger; + +#[allow(unused_imports)] +use std::collections::BTreeSet; + +pub use swagger::auth::Authorization; +use swagger::auth::Scopes; +use swagger::{ApiError, Context, XSpanId}; + +#[allow(unused_imports)] +use models; +use {Api, ContainerIdGetResponse, ContainerLookupGetResponse, ContainerPostResponse, +     CreatorIdGetResponse, CreatorLookupGetResponse, CreatorPostResponse, +     EditgroupIdAcceptPostResponse, EditgroupIdGetResponse, EditgroupPostResponse, +     EditorUsernameChangelogGetResponse, EditorUsernameGetResponse, FileIdGetResponse, +     FileLookupGetResponse, FilePostResponse, ReleaseIdGetResponse, ReleaseLookupGetResponse, +     ReleasePostResponse, WorkIdGetResponse, WorkPostResponse}; + +pub mod auth; + +header! { (Warning, "Warning") => [String] } + +mod paths { +    extern crate regex; + +    lazy_static! { +        pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(&[ +            r"^/v0/container$", +            r"^/v0/container/lookup$", +            r"^/v0/container/(?P<id>[^/?#]*)$", +            r"^/v0/creator$", +            r"^/v0/creator/lookup$", +            r"^/v0/creator/(?P<id>[^/?#]*)$", +            r"^/v0/editgroup$", +            r"^/v0/editgroup/(?P<id>[^/?#]*)$", +            r"^/v0/editgroup/(?P<id>[^/?#]*)/accept$", +            r"^/v0/editor/(?P<username>[^/?#]*)$", +            r"^/v0/editor/(?P<username>[^/?#]*)/changelog$", +            r"^/v0/file$", +            r"^/v0/file/lookup$", +            r"^/v0/file/(?P<id>[^/?#]*)$", +            r"^/v0/release$", +            r"^/v0/release/lookup$", +            r"^/v0/release/(?P<id>[^/?#]*)$", +            r"^/v0/work$", +            r"^/v0/work/(?P<id>[^/?#]*)$" +        ]).unwrap(); +    } +    pub static ID_CONTAINER: usize = 0; +    pub static ID_CONTAINER_LOOKUP: usize = 1; +    pub static ID_CONTAINER_ID: usize = 2; +    lazy_static! { +        pub static ref REGEX_CONTAINER_ID: regex::Regex = +            regex::Regex::new(r"^/v0/container/(?P<id>[^/?#]*)$").unwrap(); +    } +    pub static ID_CREATOR: usize = 3; +    pub static ID_CREATOR_LOOKUP: usize = 4; +    pub static ID_CREATOR_ID: usize = 5; +    lazy_static! { +        pub static ref REGEX_CREATOR_ID: regex::Regex = +            regex::Regex::new(r"^/v0/creator/(?P<id>[^/?#]*)$").unwrap(); +    } +    pub static ID_EDITGROUP: usize = 6; +    pub static ID_EDITGROUP_ID: usize = 7; +    lazy_static! { +        pub static ref REGEX_EDITGROUP_ID: regex::Regex = +            regex::Regex::new(r"^/v0/editgroup/(?P<id>[^/?#]*)$").unwrap(); +    } +    pub static ID_EDITGROUP_ID_ACCEPT: usize = 8; +    lazy_static! { +        pub static ref REGEX_EDITGROUP_ID_ACCEPT: regex::Regex = +            regex::Regex::new(r"^/v0/editgroup/(?P<id>[^/?#]*)/accept$").unwrap(); +    } +    pub static ID_EDITOR_USERNAME: usize = 9; +    lazy_static! { +        pub static ref REGEX_EDITOR_USERNAME: regex::Regex = +            regex::Regex::new(r"^/v0/editor/(?P<username>[^/?#]*)$").unwrap(); +    } +    pub static ID_EDITOR_USERNAME_CHANGELOG: usize = 10; +    lazy_static! { +        pub static ref REGEX_EDITOR_USERNAME_CHANGELOG: regex::Regex = +            regex::Regex::new(r"^/v0/editor/(?P<username>[^/?#]*)/changelog$").unwrap(); +    } +    pub static ID_FILE: usize = 11; +    pub static ID_FILE_LOOKUP: usize = 12; +    pub static ID_FILE_ID: usize = 13; +    lazy_static! { +        pub static ref REGEX_FILE_ID: regex::Regex = +            regex::Regex::new(r"^/v0/file/(?P<id>[^/?#]*)$").unwrap(); +    } +    pub static ID_RELEASE: usize = 14; +    pub static ID_RELEASE_LOOKUP: usize = 15; +    pub static ID_RELEASE_ID: usize = 16; +    lazy_static! { +        pub static ref REGEX_RELEASE_ID: regex::Regex = +            regex::Regex::new(r"^/v0/release/(?P<id>[^/?#]*)$").unwrap(); +    } +    pub static ID_WORK: usize = 17; +    pub static ID_WORK_ID: usize = 18; +    lazy_static! { +        pub static ref REGEX_WORK_ID: regex::Regex = +            regex::Regex::new(r"^/v0/work/(?P<id>[^/?#]*)$").unwrap(); +    } +} + +pub struct NewService<T> { +    api_impl: Arc<T>, +} + +impl<T> NewService<T> +where +    T: Api + Clone + 'static, +{ +    pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T> { +        NewService { +            api_impl: api_impl.into(), +        } +    } +} + +impl<T> hyper::server::NewService for NewService<T> +where +    T: Api + Clone + 'static, +{ +    type Request = (Request, Context); +    type Response = Response; +    type Error = Error; +    type Instance = Service<T>; + +    fn new_service(&self) -> Result<Self::Instance, io::Error> { +        Ok(Service::new(self.api_impl.clone())) +    } +} + +pub struct Service<T> { +    api_impl: Arc<T>, +} + +impl<T> Service<T> +where +    T: Api + Clone + 'static, +{ +    pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T> { +        Service { +            api_impl: api_impl.into(), +        } +    } +} + +impl<T> hyper::server::Service for Service<T> +where +    T: Api + Clone + 'static, +{ +    type Request = (Request, Context); +    type Response = Response; +    type Error = Error; +    type Future = Box<Future<Item = Response, Error = Error>>; + +    fn call(&self, (req, mut context): Self::Request) -> Self::Future { +        let api_impl = self.api_impl.clone(); +        let (method, uri, _, headers, body) = req.deconstruct(); +        let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); +        match &method { +            // ContainerIdGet - GET /container/{id} +            &hyper::Method::Get if path.matched(paths::ID_CONTAINER_ID) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_CONTAINER_ID +                    .captures(&path) +                    .unwrap_or_else(|| { +                        panic!("Path {} matched RE CONTAINER_ID in set but failed match against \"{}\"", path, paths::REGEX_CONTAINER_ID.as_str()) +                    }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<String>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.container_id_get(param_id, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                ContainerIdGetResponse::FetchASingleContainerById + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_ID_GET_FETCH_A_SINGLE_CONTAINER_BY_ID.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ContainerIdGetResponse::BadRequest + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(400).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_ID_GET_BAD_REQUEST.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ContainerIdGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_ID_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // ContainerLookupGet - GET /container/lookup +            &hyper::Method::Get if path.matched(paths::ID_CONTAINER_LOOKUP) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) +                let query_params = form_urlencoded::parse( +                    uri.query().unwrap_or_default().as_bytes(), +                ).collect::<Vec<_>>(); +                let param_issn = query_params +                    .iter() +                    .filter(|e| e.0 == "issn") +                    .map(|e| e.1.to_owned()) +                    .nth(0); +                let param_issn = match param_issn { +                    Some(param_issn) => match param_issn.parse::<String>() { +                        Ok(param_issn) => param_issn, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!( +                                "Couldn't parse query parameter issn - doesn't match schema: {}", +                                e +                            )), +                            )) +                        } +                    }, +                    None => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body("Missing required query parameter issn"), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.container_lookup_get(param_issn, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                ContainerLookupGetResponse::FindASingleContainerByExternalIdentifer + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_LOOKUP_GET_FIND_A_SINGLE_CONTAINER_BY_EXTERNAL_IDENTIFER.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ContainerLookupGetResponse::BadRequest + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(400).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_LOOKUP_GET_BAD_REQUEST.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ContainerLookupGetResponse::NoSuchContainer + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_LOOKUP_GET_NO_SUCH_CONTAINER.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ContainerLookupGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_LOOKUP_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // ContainerPost - POST /container +            &hyper::Method::Post if path.matched(paths::ID_CONTAINER) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Body parameters (note that non-required body parameters will ignore garbage +                // values, rather than causing a 400 response). Produce warning header and logs for +                // any unused fields. +                Box::new(body.concat2().then( +                    move |result| -> Box<Future<Item = Response, Error = Error>> { +                        match result { +                            Ok(body) => { +                                let mut unused_elements = Vec::new(); +                                let param_body: Option< +                                    models::ContainerEntity, +                                > = if !body.is_empty() { +                                    let deserializer = +                                        &mut serde_json::Deserializer::from_slice(&*body); + +                                    match serde_ignored::deserialize(deserializer, |path| { +                                        warn!("Ignoring unknown field in body: {}", path); +                                        unused_elements.push(path.to_string()); +                                    }) { +                                        Ok(param_body) => param_body, + +                                        Err(_) => None, +                                    } +                                } else { +                                    None +                                }; + +                                Box::new(api_impl.container_post(param_body, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        if !unused_elements.is_empty() { +                                            response.headers_mut().set(Warning(format!( +                                                "Ignoring unknown fields in body: {:?}", +                                                unused_elements +                                            ))); +                                        } + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                ContainerPostResponse::Created(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(201).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_POST_CREATED.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                ContainerPostResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_POST_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                ContainerPostResponse::GenericErrorResponse( +                                                    body, +                                                ) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CONTAINER_POST_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                            Err(e) => Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't read body parameter body: {}", e)), +                            )), +                        } +                    }, +                )) as Box<Future<Item = Response, Error = Error>> +            } + +            // CreatorIdGet - GET /creator/{id} +            &hyper::Method::Get if path.matched(paths::ID_CREATOR_ID) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_CREATOR_ID.captures(&path).unwrap_or_else(|| { +                    panic!( +                        "Path {} matched RE CREATOR_ID in set but failed match against \"{}\"", +                        path, +                        paths::REGEX_CREATOR_ID.as_str() +                    ) +                }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<String>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.creator_id_get(param_id, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                CreatorIdGetResponse::FetchASingleCreatorById( +                                                    body, +                                                ) => { +                                                    response.set_status( +                                                        StatusCode::try_from(200).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_ID_GET_FETCH_A_SINGLE_CREATOR_BY_ID.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                CreatorIdGetResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_ID_GET_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                CreatorIdGetResponse::GenericErrorResponse( +                                                    body, +                                                ) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_ID_GET_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // CreatorLookupGet - GET /creator/lookup +            &hyper::Method::Get if path.matched(paths::ID_CREATOR_LOOKUP) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) +                let query_params = form_urlencoded::parse( +                    uri.query().unwrap_or_default().as_bytes(), +                ).collect::<Vec<_>>(); +                let param_orcid = query_params +                    .iter() +                    .filter(|e| e.0 == "orcid") +                    .map(|e| e.1.to_owned()) +                    .nth(0); +                let param_orcid = match param_orcid { +                    Some(param_orcid) => match param_orcid.parse::<String>() { +                        Ok(param_orcid) => param_orcid, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!( +                                "Couldn't parse query parameter orcid - doesn't match schema: {}", +                                e +                            )), +                            )) +                        } +                    }, +                    None => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body("Missing required query parameter orcid"), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.creator_lookup_get(param_orcid, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                CreatorLookupGetResponse::FindASingleCreatorByExternalIdentifer + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_LOOKUP_GET_FIND_A_SINGLE_CREATOR_BY_EXTERNAL_IDENTIFER.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                CreatorLookupGetResponse::BadRequest + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(400).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_LOOKUP_GET_BAD_REQUEST.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                CreatorLookupGetResponse::NoSuchCreator + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_LOOKUP_GET_NO_SUCH_CREATOR.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                CreatorLookupGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_LOOKUP_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // CreatorPost - POST /creator +            &hyper::Method::Post if path.matched(paths::ID_CREATOR) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Body parameters (note that non-required body parameters will ignore garbage +                // values, rather than causing a 400 response). Produce warning header and logs for +                // any unused fields. +                Box::new(body.concat2().then( +                    move |result| -> Box<Future<Item = Response, Error = Error>> { +                        match result { +                            Ok(body) => { +                                let mut unused_elements = Vec::new(); +                                let param_body: Option< +                                    models::CreatorEntity, +                                > = if !body.is_empty() { +                                    let deserializer = +                                        &mut serde_json::Deserializer::from_slice(&*body); + +                                    match serde_ignored::deserialize(deserializer, |path| { +                                        warn!("Ignoring unknown field in body: {}", path); +                                        unused_elements.push(path.to_string()); +                                    }) { +                                        Ok(param_body) => param_body, + +                                        Err(_) => None, +                                    } +                                } else { +                                    None +                                }; + +                                Box::new(api_impl.creator_post(param_body, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        if !unused_elements.is_empty() { +                                            response.headers_mut().set(Warning(format!( +                                                "Ignoring unknown fields in body: {:?}", +                                                unused_elements +                                            ))); +                                        } + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                CreatorPostResponse::Created(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(201).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType( +                                                        mimetypes::responses::CREATOR_POST_CREATED +                                                            .clone(), +                                                    )); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                CreatorPostResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_POST_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                CreatorPostResponse::GenericErrorResponse(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::CREATOR_POST_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                            Err(e) => Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't read body parameter body: {}", e)), +                            )), +                        } +                    }, +                )) as Box<Future<Item = Response, Error = Error>> +            } + +            // EditgroupIdAcceptPost - POST /editgroup/{id}/accept +            &hyper::Method::Post if path.matched(paths::ID_EDITGROUP_ID_ACCEPT) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_EDITGROUP_ID_ACCEPT +                    .captures(&path) +                    .unwrap_or_else(|| { +                        panic!("Path {} matched RE EDITGROUP_ID_ACCEPT in set but failed match against \"{}\"", path, paths::REGEX_EDITGROUP_ID_ACCEPT.as_str()) +                    }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<i32>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new( +                                    api_impl.editgroup_id_accept_post(param_id, &context).then( +                                        move |result| { +                                            let mut response = Response::new(); +                                            context.x_span_id.as_ref().map(|header| { +                                                response.headers_mut().set(XSpanId(header.clone())) +                                            }); + +                                            match result { +                                            Ok(rsp) => match rsp { +                                                EditgroupIdAcceptPostResponse::MergedEditgroupSuccessfully_ + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_ACCEPT_POST_MERGED_EDITGROUP_SUCCESSFULLY_.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditgroupIdAcceptPostResponse::EditgroupIsInAnUnmergableState + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(400).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_ACCEPT_POST_EDITGROUP_IS_IN_AN_UNMERGABLE_STATE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditgroupIdAcceptPostResponse::NoSuchEditgroup + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_ACCEPT_POST_NO_SUCH_EDITGROUP.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditgroupIdAcceptPostResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_ACCEPT_POST_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                            future::ok(response) +                                        }, +                                    ), +                                ) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // EditgroupIdGet - GET /editgroup/{id} +            &hyper::Method::Get if path.matched(paths::ID_EDITGROUP_ID) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_EDITGROUP_ID +                    .captures(&path) +                    .unwrap_or_else(|| { +                        panic!("Path {} matched RE EDITGROUP_ID in set but failed match against \"{}\"", path, paths::REGEX_EDITGROUP_ID.as_str()) +                    }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<i32>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.editgroup_id_get(param_id, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                EditgroupIdGetResponse::FetchEditgroupByIdentifier + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_GET_FETCH_EDITGROUP_BY_IDENTIFIER.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditgroupIdGetResponse::NoSuchEditgroup + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_GET_NO_SUCH_EDITGROUP.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditgroupIdGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_ID_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // EditgroupPost - POST /editgroup +            &hyper::Method::Post if path.matched(paths::ID_EDITGROUP) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.editgroup_post(&context).then(move |result| { +                                    let mut response = Response::new(); +                                    context.x_span_id.as_ref().map(|header| { +                                        response.headers_mut().set(XSpanId(header.clone())) +                                    }); + +                                    match result { +                                        Ok(rsp) => match rsp { +                                            EditgroupPostResponse::SuccessfullyCreated(body) => { +                                                response +                                                    .set_status(StatusCode::try_from(201).unwrap()); + +                                                response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_POST_SUCCESSFULLY_CREATED.clone())); + +                                                let body = serde_json::to_string(&body) +                                                    .expect("impossible to fail to serialize"); + +                                                response.set_body(body); +                                            } +                                            EditgroupPostResponse::InvalidRequestParameters( +                                                body, +                                            ) => { +                                                response +                                                    .set_status(StatusCode::try_from(400).unwrap()); + +                                                response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_POST_INVALID_REQUEST_PARAMETERS.clone())); + +                                                let body = serde_json::to_string(&body) +                                                    .expect("impossible to fail to serialize"); + +                                                response.set_body(body); +                                            } +                                            EditgroupPostResponse::GenericErrorResponse(body) => { +                                                response +                                                    .set_status(StatusCode::try_from(0).unwrap()); + +                                                response.headers_mut().set(ContentType(mimetypes::responses::EDITGROUP_POST_GENERIC_ERROR_RESPONSE.clone())); + +                                                let body = serde_json::to_string(&body) +                                                    .expect("impossible to fail to serialize"); + +                                                response.set_body(body); +                                            } +                                        }, +                                        Err(_) => { +                                            // Application code returned an error. This should not happen, as the implementation should +                                            // return a valid response. +                                            response.set_status(StatusCode::InternalServerError); +                                            response.set_body("An internal error occurred"); +                                        } +                                    } + +                                    future::ok(response) +                                })) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // EditorUsernameChangelogGet - GET /editor/{username}/changelog +            &hyper::Method::Get if path.matched(paths::ID_EDITOR_USERNAME_CHANGELOG) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_EDITOR_USERNAME_CHANGELOG +                    .captures(&path) +                    .unwrap_or_else(|| { +                        panic!("Path {} matched RE EDITOR_USERNAME_CHANGELOG in set but failed match against \"{}\"", path, paths::REGEX_EDITOR_USERNAME_CHANGELOG.as_str()) +                    }); + +                let param_username = match percent_encoding::percent_decode( +                    path_params["username"].as_bytes(), +                ).decode_utf8() +                { +                    Ok(param_username) => match param_username.parse::<String>() { +                        Ok(param_username) => param_username, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!( +                                        "Couldn't parse path parameter username: {}", +                                        e +                                    )), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["username"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new( +                                    api_impl +                                        .editor_username_changelog_get(param_username, &context) +                                        .then(move |result| { +                                            let mut response = Response::new(); +                                            context.x_span_id.as_ref().map(|header| { +                                                response.headers_mut().set(XSpanId(header.clone())) +                                            }); + +                                            match result { +                                            Ok(rsp) => match rsp { +                                                EditorUsernameChangelogGetResponse::FindChanges_ + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITOR_USERNAME_CHANGELOG_GET_FIND_CHANGES_.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditorUsernameChangelogGetResponse::UsernameNotFound + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITOR_USERNAME_CHANGELOG_GET_USERNAME_NOT_FOUND.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditorUsernameChangelogGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITOR_USERNAME_CHANGELOG_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                            future::ok(response) +                                        }), +                                ) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // EditorUsernameGet - GET /editor/{username} +            &hyper::Method::Get if path.matched(paths::ID_EDITOR_USERNAME) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_EDITOR_USERNAME.captures(&path).unwrap_or_else( +                    || { +                        panic!("Path {} matched RE EDITOR_USERNAME in set but failed match against \"{}\"", path, paths::REGEX_EDITOR_USERNAME.as_str()) +                    }, +                ); + +                let param_username = match percent_encoding::percent_decode( +                    path_params["username"].as_bytes(), +                ).decode_utf8() +                { +                    Ok(param_username) => match param_username.parse::<String>() { +                        Ok(param_username) => param_username, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!( +                                        "Couldn't parse path parameter username: {}", +                                        e +                                    )), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["username"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new( +                                    api_impl.editor_username_get(param_username, &context).then( +                                        move |result| { +                                            let mut response = Response::new(); +                                            context.x_span_id.as_ref().map(|header| { +                                                response.headers_mut().set(XSpanId(header.clone())) +                                            }); + +                                            match result { +                                            Ok(rsp) => match rsp { +                                                EditorUsernameGetResponse::FetchGenericInformationAboutAnEditor + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITOR_USERNAME_GET_FETCH_GENERIC_INFORMATION_ABOUT_AN_EDITOR.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditorUsernameGetResponse::UsernameNotFound + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITOR_USERNAME_GET_USERNAME_NOT_FOUND.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                EditorUsernameGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::EDITOR_USERNAME_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                            future::ok(response) +                                        }, +                                    ), +                                ) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // FileIdGet - GET /file/{id} +            &hyper::Method::Get if path.matched(paths::ID_FILE_ID) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_FILE_ID.captures(&path).unwrap_or_else(|| { +                    panic!( +                        "Path {} matched RE FILE_ID in set but failed match against \"{}\"", +                        path, +                        paths::REGEX_FILE_ID.as_str() +                    ) +                }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<String>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.file_id_get(param_id, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                FileIdGetResponse::FetchASingleFileById(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(200).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_ID_GET_FETCH_A_SINGLE_FILE_BY_ID.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                FileIdGetResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_ID_GET_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                FileIdGetResponse::GenericErrorResponse(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_ID_GET_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // FileLookupGet - GET /file/lookup +            &hyper::Method::Get if path.matched(paths::ID_FILE_LOOKUP) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) +                let query_params = form_urlencoded::parse( +                    uri.query().unwrap_or_default().as_bytes(), +                ).collect::<Vec<_>>(); +                let param_sha1 = query_params +                    .iter() +                    .filter(|e| e.0 == "sha1") +                    .map(|e| e.1.to_owned()) +                    .nth(0); +                let param_sha1 = match param_sha1 { +                    Some(param_sha1) => match param_sha1.parse::<String>() { +                        Ok(param_sha1) => param_sha1, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!( +                                "Couldn't parse query parameter sha1 - doesn't match schema: {}", +                                e +                            )), +                            )) +                        } +                    }, +                    None => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body("Missing required query parameter sha1"), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.file_lookup_get(param_sha1, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                FileLookupGetResponse::FindASingleFileByExternalIdentifer + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_LOOKUP_GET_FIND_A_SINGLE_FILE_BY_EXTERNAL_IDENTIFER.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                FileLookupGetResponse::BadRequest + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(400).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_LOOKUP_GET_BAD_REQUEST.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                FileLookupGetResponse::NoSuchFile + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_LOOKUP_GET_NO_SUCH_FILE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                FileLookupGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_LOOKUP_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // FilePost - POST /file +            &hyper::Method::Post if path.matched(paths::ID_FILE) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Body parameters (note that non-required body parameters will ignore garbage +                // values, rather than causing a 400 response). Produce warning header and logs for +                // any unused fields. +                Box::new(body.concat2().then( +                    move |result| -> Box<Future<Item = Response, Error = Error>> { +                        match result { +                            Ok(body) => { +                                let mut unused_elements = Vec::new(); +                                let param_body: Option< +                                    models::FileEntity, +                                > = if !body.is_empty() { +                                    let deserializer = +                                        &mut serde_json::Deserializer::from_slice(&*body); + +                                    match serde_ignored::deserialize(deserializer, |path| { +                                        warn!("Ignoring unknown field in body: {}", path); +                                        unused_elements.push(path.to_string()); +                                    }) { +                                        Ok(param_body) => param_body, + +                                        Err(_) => None, +                                    } +                                } else { +                                    None +                                }; + +                                Box::new(api_impl.file_post(param_body, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        if !unused_elements.is_empty() { +                                            response.headers_mut().set(Warning(format!( +                                                "Ignoring unknown fields in body: {:?}", +                                                unused_elements +                                            ))); +                                        } + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                FilePostResponse::Created(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(201).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType( +                                                        mimetypes::responses::FILE_POST_CREATED +                                                            .clone(), +                                                    )); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                FilePostResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType( +                                                        mimetypes::responses::FILE_POST_BAD_REQUEST +                                                            .clone(), +                                                    )); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                FilePostResponse::GenericErrorResponse(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::FILE_POST_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                            Err(e) => Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't read body parameter body: {}", e)), +                            )), +                        } +                    }, +                )) as Box<Future<Item = Response, Error = Error>> +            } + +            // ReleaseIdGet - GET /release/{id} +            &hyper::Method::Get if path.matched(paths::ID_RELEASE_ID) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_RELEASE_ID.captures(&path).unwrap_or_else(|| { +                    panic!( +                        "Path {} matched RE RELEASE_ID in set but failed match against \"{}\"", +                        path, +                        paths::REGEX_RELEASE_ID.as_str() +                    ) +                }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<String>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.release_id_get(param_id, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                ReleaseIdGetResponse::FetchASingleReleaseById( +                                                    body, +                                                ) => { +                                                    response.set_status( +                                                        StatusCode::try_from(200).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_ID_GET_FETCH_A_SINGLE_RELEASE_BY_ID.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                ReleaseIdGetResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_ID_GET_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                ReleaseIdGetResponse::GenericErrorResponse( +                                                    body, +                                                ) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_ID_GET_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // ReleaseLookupGet - GET /release/lookup +            &hyper::Method::Get if path.matched(paths::ID_RELEASE_LOOKUP) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) +                let query_params = form_urlencoded::parse( +                    uri.query().unwrap_or_default().as_bytes(), +                ).collect::<Vec<_>>(); +                let param_doi = query_params +                    .iter() +                    .filter(|e| e.0 == "doi") +                    .map(|e| e.1.to_owned()) +                    .nth(0); +                let param_doi = match param_doi { +                    Some(param_doi) => match param_doi.parse::<String>() { +                        Ok(param_doi) => param_doi, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!( +                                    "Couldn't parse query parameter doi - doesn't match schema: {}", +                                    e +                                )), +                            )) +                        } +                    }, +                    None => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body("Missing required query parameter doi"), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.release_lookup_get(param_doi, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                ReleaseLookupGetResponse::FindASingleReleaseByExternalIdentifer + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(200).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_LOOKUP_GET_FIND_A_SINGLE_RELEASE_BY_EXTERNAL_IDENTIFER.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ReleaseLookupGetResponse::BadRequest + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(400).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_LOOKUP_GET_BAD_REQUEST.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ReleaseLookupGetResponse::NoSuchRelease + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(404).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_LOOKUP_GET_NO_SUCH_RELEASE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                                ReleaseLookupGetResponse::GenericErrorResponse + +                                                    (body) + + +                                                => { +                                                    response.set_status(StatusCode::try_from(0).unwrap()); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_LOOKUP_GET_GENERIC_ERROR_RESPONSE.clone())); + + +                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                }, +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response.set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            }, +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // ReleasePost - POST /release +            &hyper::Method::Post if path.matched(paths::ID_RELEASE) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Body parameters (note that non-required body parameters will ignore garbage +                // values, rather than causing a 400 response). Produce warning header and logs for +                // any unused fields. +                Box::new(body.concat2().then( +                    move |result| -> Box<Future<Item = Response, Error = Error>> { +                        match result { +                            Ok(body) => { +                                let mut unused_elements = Vec::new(); +                                let param_body: Option< +                                    models::ReleaseEntity, +                                > = if !body.is_empty() { +                                    let deserializer = +                                        &mut serde_json::Deserializer::from_slice(&*body); + +                                    match serde_ignored::deserialize(deserializer, |path| { +                                        warn!("Ignoring unknown field in body: {}", path); +                                        unused_elements.push(path.to_string()); +                                    }) { +                                        Ok(param_body) => param_body, + +                                        Err(_) => None, +                                    } +                                } else { +                                    None +                                }; + +                                Box::new(api_impl.release_post(param_body, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        if !unused_elements.is_empty() { +                                            response.headers_mut().set(Warning(format!( +                                                "Ignoring unknown fields in body: {:?}", +                                                unused_elements +                                            ))); +                                        } + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                ReleasePostResponse::Created(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(201).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType( +                                                        mimetypes::responses::RELEASE_POST_CREATED +                                                            .clone(), +                                                    )); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                ReleasePostResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_POST_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                ReleasePostResponse::GenericErrorResponse(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::RELEASE_POST_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                            Err(e) => Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't read body parameter body: {}", e)), +                            )), +                        } +                    }, +                )) as Box<Future<Item = Response, Error = Error>> +            } + +            // WorkIdGet - GET /work/{id} +            &hyper::Method::Get if path.matched(paths::ID_WORK_ID) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Path parameters +                let path = uri.path().to_string(); +                let path_params = paths::REGEX_WORK_ID.captures(&path).unwrap_or_else(|| { +                    panic!( +                        "Path {} matched RE WORK_ID in set but failed match against \"{}\"", +                        path, +                        paths::REGEX_WORK_ID.as_str() +                    ) +                }); + +                let param_id = match percent_encoding::percent_decode(path_params["id"].as_bytes()) +                    .decode_utf8() +                { +                    Ok(param_id) => match param_id.parse::<String>() { +                        Ok(param_id) => param_id, +                        Err(e) => { +                            return Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't parse path parameter id: {}", e)), +                            )) +                        } +                    }, +                    Err(_) => { +                        return Box::new(future::ok( +                            Response::new() +                                .with_status(StatusCode::BadRequest) +                                .with_body(format!( +                                    "Couldn't percent-decode path parameter as UTF-8: {}", +                                    &path_params["id"] +                                )), +                        )) +                    } +                }; + +                Box::new( +                    ({ +                        { +                            { +                                Box::new(api_impl.work_id_get(param_id, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                WorkIdGetResponse::FetchASingleWorkById(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(200).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::WORK_ID_GET_FETCH_A_SINGLE_WORK_BY_ID.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                WorkIdGetResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::WORK_ID_GET_BAD_REQUEST.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                WorkIdGetResponse::GenericErrorResponse(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::WORK_ID_GET_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                        } +                    }), +                ) as Box<Future<Item = Response, Error = Error>> +            } + +            // WorkPost - POST /work +            &hyper::Method::Post if path.matched(paths::ID_WORK) => { +                if context.x_span_id.is_none() { +                    context.x_span_id = Some( +                        headers +                            .get::<XSpanId>() +                            .map(XSpanId::to_string) +                            .unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()), +                    ); +                } + +                // Body parameters (note that non-required body parameters will ignore garbage +                // values, rather than causing a 400 response). Produce warning header and logs for +                // any unused fields. +                Box::new(body.concat2().then( +                    move |result| -> Box<Future<Item = Response, Error = Error>> { +                        match result { +                            Ok(body) => { +                                let mut unused_elements = Vec::new(); +                                let param_body: Option< +                                    models::WorkEntity, +                                > = if !body.is_empty() { +                                    let deserializer = +                                        &mut serde_json::Deserializer::from_slice(&*body); + +                                    match serde_ignored::deserialize(deserializer, |path| { +                                        warn!("Ignoring unknown field in body: {}", path); +                                        unused_elements.push(path.to_string()); +                                    }) { +                                        Ok(param_body) => param_body, + +                                        Err(_) => None, +                                    } +                                } else { +                                    None +                                }; + +                                Box::new(api_impl.work_post(param_body, &context).then( +                                    move |result| { +                                        let mut response = Response::new(); +                                        context.x_span_id.as_ref().map(|header| { +                                            response.headers_mut().set(XSpanId(header.clone())) +                                        }); + +                                        if !unused_elements.is_empty() { +                                            response.headers_mut().set(Warning(format!( +                                                "Ignoring unknown fields in body: {:?}", +                                                unused_elements +                                            ))); +                                        } + +                                        match result { +                                            Ok(rsp) => match rsp { +                                                WorkPostResponse::Created(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(201).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType( +                                                        mimetypes::responses::WORK_POST_CREATED +                                                            .clone(), +                                                    )); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                WorkPostResponse::BadRequest(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(400).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType( +                                                        mimetypes::responses::WORK_POST_BAD_REQUEST +                                                            .clone(), +                                                    )); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                                WorkPostResponse::GenericErrorResponse(body) => { +                                                    response.set_status( +                                                        StatusCode::try_from(0).unwrap(), +                                                    ); + +                                                    response.headers_mut().set(ContentType(mimetypes::responses::WORK_POST_GENERIC_ERROR_RESPONSE.clone())); + +                                                    let body = serde_json::to_string(&body) +                                                        .expect("impossible to fail to serialize"); + +                                                    response.set_body(body); +                                                } +                                            }, +                                            Err(_) => { +                                                // Application code returned an error. This should not happen, as the implementation should +                                                // return a valid response. +                                                response +                                                    .set_status(StatusCode::InternalServerError); +                                                response.set_body("An internal error occurred"); +                                            } +                                        } + +                                        future::ok(response) +                                    }, +                                )) +                            } +                            Err(e) => Box::new(future::ok( +                                Response::new() +                                    .with_status(StatusCode::BadRequest) +                                    .with_body(format!("Couldn't read body parameter body: {}", e)), +                            )), +                        } +                    }, +                )) as Box<Future<Item = Response, Error = Error>> +            } + +            _ => Box::new(future::ok( +                Response::new().with_status(StatusCode::NotFound), +            )) as Box<Future<Item = Response, Error = Error>>, +        } +    } +} | 
