aboutsummaryrefslogtreecommitdiffstats
path: root/rust/fatcat-api/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/fatcat-api/src')
-rw-r--r--rust/fatcat-api/src/client/mod.rs2573
-rw-r--r--rust/fatcat-api/src/lib.rs599
-rw-r--r--rust/fatcat-api/src/mimetypes.rs313
-rw-r--r--rust/fatcat-api/src/models.rs392
-rw-r--r--rust/fatcat-api/src/server/auth.rs93
-rw-r--r--rust/fatcat-api/src/server/mod.rs2485
6 files changed, 6455 insertions, 0 deletions
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(&param_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(&param_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(&param_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(&param_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(&param_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(&param_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(&param_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(&param_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(&param_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 (\&quot;live\&quot;)
+ 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>>,
+ }
+ }
+}