From bcb9d2c6793b39b165caf9e63c4803d2a28e9876 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Sun, 27 May 2018 15:45:03 -0700 Subject: batch POST methods --- rust/fatcat-api/src/client.rs | 332 +++++++++++++++++++++++- rust/fatcat-api/src/lib.rs | 100 ++++++++ rust/fatcat-api/src/mimetypes.rs | 100 ++++++++ rust/fatcat-api/src/models.rs | 72 +++--- rust/fatcat-api/src/server.rs | 537 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 1099 insertions(+), 42 deletions(-) (limited to 'rust/fatcat-api/src') diff --git a/rust/fatcat-api/src/client.rs b/rust/fatcat-api/src/client.rs index d81d251f..e9f8bf0e 100644 --- a/rust/fatcat-api/src/client.rs +++ b/rust/fatcat-api/src/client.rs @@ -34,9 +34,10 @@ 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}; +use {Api, ContainerBatchPostResponse, ContainerIdGetResponse, ContainerLookupGetResponse, ContainerPostResponse, CreatorBatchPostResponse, CreatorIdGetResponse, CreatorLookupGetResponse, + CreatorPostResponse, EditgroupIdAcceptPostResponse, EditgroupIdGetResponse, EditgroupPostResponse, EditorUsernameChangelogGetResponse, EditorUsernameGetResponse, FileBatchPostResponse, + FileIdGetResponse, FileLookupGetResponse, FilePostResponse, ReleaseBatchPostResponse, ReleaseIdGetResponse, ReleaseLookupGetResponse, ReleasePostResponse, WorkBatchPostResponse, + 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: T, correct_scheme: Option<&'static str>) -> Result { @@ -161,6 +162,71 @@ impl Client { } impl Api for Client { + fn container_batch_post(&self, param_entity_list: &Vec, context: &Context) -> Box + Send> { + let url = format!("{}/v0/container/batch", self.base_path); + + let body = serde_json::to_string(¶m_entity_list).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::CONTAINER_BATCH_POST.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 201 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(&buf)?; + + Ok(ContainerBatchPostResponse::CreatedEntities(body)) + } + 400 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(ContainerBatchPostResponse::BadRequest(body)) + } + 404 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(ContainerBatchPostResponse::NotFound(body)) + } + 0 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(ContainerBatchPostResponse::GenericError(body)) + } + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, response.headers, debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + fn container_id_get(&self, param_id: String, context: &Context) -> Box + Send> { let url = format!("{}/v0/container/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); @@ -349,6 +415,71 @@ impl Api for Client { Box::new(futures::done(result)) } + fn creator_batch_post(&self, param_entity_list: &Vec, context: &Context) -> Box + Send> { + let url = format!("{}/v0/creator/batch", self.base_path); + + let body = serde_json::to_string(¶m_entity_list).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::CREATOR_BATCH_POST.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 201 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(&buf)?; + + Ok(CreatorBatchPostResponse::CreatedEntities(body)) + } + 400 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(CreatorBatchPostResponse::BadRequest(body)) + } + 404 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(CreatorBatchPostResponse::NotFound(body)) + } + 0 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(CreatorBatchPostResponse::GenericError(body)) + } + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, response.headers, debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + fn creator_id_get(&self, param_id: String, context: &Context) -> Box + Send> { let url = format!("{}/v0/creator/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); @@ -829,6 +960,71 @@ impl Api for Client { Box::new(futures::done(result)) } + fn file_batch_post(&self, param_entity_list: &Vec, context: &Context) -> Box + Send> { + let url = format!("{}/v0/file/batch", self.base_path); + + let body = serde_json::to_string(¶m_entity_list).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::FILE_BATCH_POST.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 201 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(&buf)?; + + Ok(FileBatchPostResponse::CreatedEntities(body)) + } + 400 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(FileBatchPostResponse::BadRequest(body)) + } + 404 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(FileBatchPostResponse::NotFound(body)) + } + 0 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(FileBatchPostResponse::GenericError(body)) + } + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, response.headers, debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + fn file_id_get(&self, param_id: String, context: &Context) -> Box + Send> { let url = format!("{}/v0/file/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); @@ -1017,6 +1213,71 @@ impl Api for Client { Box::new(futures::done(result)) } + fn release_batch_post(&self, param_entity_list: &Vec, context: &Context) -> Box + Send> { + let url = format!("{}/v0/release/batch", self.base_path); + + let body = serde_json::to_string(¶m_entity_list).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::RELEASE_BATCH_POST.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 201 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(&buf)?; + + Ok(ReleaseBatchPostResponse::CreatedEntities(body)) + } + 400 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(ReleaseBatchPostResponse::BadRequest(body)) + } + 404 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(ReleaseBatchPostResponse::NotFound(body)) + } + 0 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(ReleaseBatchPostResponse::GenericError(body)) + } + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, response.headers, debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + fn release_id_get(&self, param_id: String, context: &Context) -> Box + Send> { let url = format!("{}/v0/release/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); @@ -1205,6 +1466,71 @@ impl Api for Client { Box::new(futures::done(result)) } + fn work_batch_post(&self, param_entity_list: &Vec, context: &Context) -> Box + Send> { + let url = format!("{}/v0/work/batch", self.base_path); + + let body = serde_json::to_string(¶m_entity_list).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::WORK_BATCH_POST.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 201 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(&buf)?; + + Ok(WorkBatchPostResponse::CreatedEntities(body)) + } + 400 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(WorkBatchPostResponse::BadRequest(body)) + } + 404 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(WorkBatchPostResponse::NotFound(body)) + } + 0 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + Ok(WorkBatchPostResponse::GenericError(body)) + } + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", code, response.headers, debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + fn work_id_get(&self, param_id: String, context: &Context) -> Box + Send> { let url = format!("{}/v0/work/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); diff --git a/rust/fatcat-api/src/lib.rs b/rust/fatcat-api/src/lib.rs index dca1aa35..1a46fbeb 100644 --- a/rust/fatcat-api/src/lib.rs +++ b/rust/fatcat-api/src/lib.rs @@ -32,6 +32,18 @@ mod mimetypes; pub use swagger::{ApiError, Context, ContextWrapper}; +#[derive(Debug, PartialEq)] +pub enum ContainerBatchPostResponse { + /// Created Entities + CreatedEntities(Vec), + /// Bad Request + BadRequest(models::ErrorResponse), + /// Not Found + NotFound(models::ErrorResponse), + /// Generic Error + GenericError(models::ErrorResponse), +} + #[derive(Debug, PartialEq)] pub enum ContainerIdGetResponse { /// Found Entity @@ -68,6 +80,18 @@ pub enum ContainerPostResponse { GenericError(models::ErrorResponse), } +#[derive(Debug, PartialEq)] +pub enum CreatorBatchPostResponse { + /// Created Entities + CreatedEntities(Vec), + /// Bad Request + BadRequest(models::ErrorResponse), + /// Not Found + NotFound(models::ErrorResponse), + /// Generic Error + GenericError(models::ErrorResponse), +} + #[derive(Debug, PartialEq)] pub enum CreatorIdGetResponse { /// Found Entity @@ -158,6 +182,18 @@ pub enum EditorUsernameGetResponse { GenericError(models::ErrorResponse), } +#[derive(Debug, PartialEq)] +pub enum FileBatchPostResponse { + /// Created Entities + CreatedEntities(Vec), + /// Bad Request + BadRequest(models::ErrorResponse), + /// Not Found + NotFound(models::ErrorResponse), + /// Generic Error + GenericError(models::ErrorResponse), +} + #[derive(Debug, PartialEq)] pub enum FileIdGetResponse { /// Found Entity @@ -194,6 +230,18 @@ pub enum FilePostResponse { GenericError(models::ErrorResponse), } +#[derive(Debug, PartialEq)] +pub enum ReleaseBatchPostResponse { + /// Created Entities + CreatedEntities(Vec), + /// Bad Request + BadRequest(models::ErrorResponse), + /// Not Found + NotFound(models::ErrorResponse), + /// Generic Error + GenericError(models::ErrorResponse), +} + #[derive(Debug, PartialEq)] pub enum ReleaseIdGetResponse { /// Found Entity @@ -230,6 +278,18 @@ pub enum ReleasePostResponse { GenericError(models::ErrorResponse), } +#[derive(Debug, PartialEq)] +pub enum WorkBatchPostResponse { + /// Created Entities + CreatedEntities(Vec), + /// Bad Request + BadRequest(models::ErrorResponse), + /// Not Found + NotFound(models::ErrorResponse), + /// Generic Error + GenericError(models::ErrorResponse), +} + #[derive(Debug, PartialEq)] pub enum WorkIdGetResponse { /// Found Entity @@ -256,12 +316,16 @@ pub enum WorkPostResponse { /// API pub trait Api { + fn container_batch_post(&self, entity_list: &Vec, context: &Context) -> Box + Send>; + fn container_id_get(&self, id: String, context: &Context) -> Box + Send>; fn container_lookup_get(&self, issnl: String, context: &Context) -> Box + Send>; fn container_post(&self, entity: models::ContainerEntity, context: &Context) -> Box + Send>; + fn creator_batch_post(&self, entity_list: &Vec, context: &Context) -> Box + Send>; + fn creator_id_get(&self, id: String, context: &Context) -> Box + Send>; fn creator_lookup_get(&self, orcid: String, context: &Context) -> Box + Send>; @@ -278,18 +342,24 @@ pub trait Api { fn editor_username_get(&self, username: String, context: &Context) -> Box + Send>; + fn file_batch_post(&self, entity_list: &Vec, context: &Context) -> Box + Send>; + fn file_id_get(&self, id: String, context: &Context) -> Box + Send>; fn file_lookup_get(&self, sha1: String, context: &Context) -> Box + Send>; fn file_post(&self, entity: models::FileEntity, context: &Context) -> Box + Send>; + fn release_batch_post(&self, entity_list: &Vec, context: &Context) -> Box + Send>; + fn release_id_get(&self, id: String, context: &Context) -> Box + Send>; fn release_lookup_get(&self, doi: String, context: &Context) -> Box + Send>; fn release_post(&self, entity: models::ReleaseEntity, context: &Context) -> Box + Send>; + fn work_batch_post(&self, entity_list: &Vec, context: &Context) -> Box + Send>; + fn work_id_get(&self, id: String, context: &Context) -> Box + Send>; fn work_post(&self, entity: models::WorkEntity, context: &Context) -> Box + Send>; @@ -297,12 +367,16 @@ pub trait Api { /// API without a `Context` pub trait ApiNoContext { + fn container_batch_post(&self, entity_list: &Vec) -> Box + Send>; + fn container_id_get(&self, id: String) -> Box + Send>; fn container_lookup_get(&self, issnl: String) -> Box + Send>; fn container_post(&self, entity: models::ContainerEntity) -> Box + Send>; + fn creator_batch_post(&self, entity_list: &Vec) -> Box + Send>; + fn creator_id_get(&self, id: String) -> Box + Send>; fn creator_lookup_get(&self, orcid: String) -> Box + Send>; @@ -319,18 +393,24 @@ pub trait ApiNoContext { fn editor_username_get(&self, username: String) -> Box + Send>; + fn file_batch_post(&self, entity_list: &Vec) -> Box + Send>; + fn file_id_get(&self, id: String) -> Box + Send>; fn file_lookup_get(&self, sha1: String) -> Box + Send>; fn file_post(&self, entity: models::FileEntity) -> Box + Send>; + fn release_batch_post(&self, entity_list: &Vec) -> Box + Send>; + fn release_id_get(&self, id: String) -> Box + Send>; fn release_lookup_get(&self, doi: String) -> Box + Send>; fn release_post(&self, entity: models::ReleaseEntity) -> Box + Send>; + fn work_batch_post(&self, entity_list: &Vec) -> Box + Send>; + fn work_id_get(&self, id: String) -> Box + Send>; fn work_post(&self, entity: models::WorkEntity) -> Box + Send>; @@ -352,6 +432,10 @@ impl<'a, T: Api + Sized> ContextWrapperExt<'a> for T { } impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { + fn container_batch_post(&self, entity_list: &Vec) -> Box + Send> { + self.api().container_batch_post(entity_list, &self.context()) + } + fn container_id_get(&self, id: String) -> Box + Send> { self.api().container_id_get(id, &self.context()) } @@ -364,6 +448,10 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().container_post(entity, &self.context()) } + fn creator_batch_post(&self, entity_list: &Vec) -> Box + Send> { + self.api().creator_batch_post(entity_list, &self.context()) + } + fn creator_id_get(&self, id: String) -> Box + Send> { self.api().creator_id_get(id, &self.context()) } @@ -396,6 +484,10 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().editor_username_get(username, &self.context()) } + fn file_batch_post(&self, entity_list: &Vec) -> Box + Send> { + self.api().file_batch_post(entity_list, &self.context()) + } + fn file_id_get(&self, id: String) -> Box + Send> { self.api().file_id_get(id, &self.context()) } @@ -408,6 +500,10 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().file_post(entity, &self.context()) } + fn release_batch_post(&self, entity_list: &Vec) -> Box + Send> { + self.api().release_batch_post(entity_list, &self.context()) + } + fn release_id_get(&self, id: String) -> Box + Send> { self.api().release_id_get(id, &self.context()) } @@ -420,6 +516,10 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().release_post(entity, &self.context()) } + fn work_batch_post(&self, entity_list: &Vec) -> Box + Send> { + self.api().work_batch_post(entity_list, &self.context()) + } + fn work_id_get(&self, id: String) -> Box + Send> { self.api().work_id_get(id, &self.context()) } diff --git a/rust/fatcat-api/src/mimetypes.rs b/rust/fatcat-api/src/mimetypes.rs index 5814890f..7b85cac5 100644 --- a/rust/fatcat-api/src/mimetypes.rs +++ b/rust/fatcat-api/src/mimetypes.rs @@ -4,6 +4,22 @@ 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 ContainerBatchPost + lazy_static! { + pub static ref CONTAINER_BATCH_POST_CREATED_ENTITIES: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for ContainerBatchPost + lazy_static! { + pub static ref CONTAINER_BATCH_POST_BAD_REQUEST: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for ContainerBatchPost + lazy_static! { + pub static ref CONTAINER_BATCH_POST_NOT_FOUND: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for ContainerBatchPost + lazy_static! { + pub static ref CONTAINER_BATCH_POST_GENERIC_ERROR: Mime = mime!(Application / Json); + } /// Create Mime objects for the response content types for ContainerIdGet lazy_static! { pub static ref CONTAINER_ID_GET_FOUND_ENTITY: Mime = mime!(Application / Json); @@ -52,6 +68,22 @@ pub mod responses { lazy_static! { pub static ref CONTAINER_POST_GENERIC_ERROR: Mime = mime!(Application / Json); } + /// Create Mime objects for the response content types for CreatorBatchPost + lazy_static! { + pub static ref CREATOR_BATCH_POST_CREATED_ENTITIES: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for CreatorBatchPost + lazy_static! { + pub static ref CREATOR_BATCH_POST_BAD_REQUEST: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for CreatorBatchPost + lazy_static! { + pub static ref CREATOR_BATCH_POST_NOT_FOUND: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for CreatorBatchPost + lazy_static! { + pub static ref CREATOR_BATCH_POST_GENERIC_ERROR: Mime = mime!(Application / Json); + } /// Create Mime objects for the response content types for CreatorIdGet lazy_static! { pub static ref CREATOR_ID_GET_FOUND_ENTITY: Mime = mime!(Application / Json); @@ -168,6 +200,22 @@ pub mod responses { lazy_static! { pub static ref EDITOR_USERNAME_GET_GENERIC_ERROR: Mime = mime!(Application / Json); } + /// Create Mime objects for the response content types for FileBatchPost + lazy_static! { + pub static ref FILE_BATCH_POST_CREATED_ENTITIES: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for FileBatchPost + lazy_static! { + pub static ref FILE_BATCH_POST_BAD_REQUEST: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for FileBatchPost + lazy_static! { + pub static ref FILE_BATCH_POST_NOT_FOUND: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for FileBatchPost + lazy_static! { + pub static ref FILE_BATCH_POST_GENERIC_ERROR: Mime = mime!(Application / Json); + } /// Create Mime objects for the response content types for FileIdGet lazy_static! { pub static ref FILE_ID_GET_FOUND_ENTITY: Mime = mime!(Application / Json); @@ -216,6 +264,22 @@ pub mod responses { lazy_static! { pub static ref FILE_POST_GENERIC_ERROR: Mime = mime!(Application / Json); } + /// Create Mime objects for the response content types for ReleaseBatchPost + lazy_static! { + pub static ref RELEASE_BATCH_POST_CREATED_ENTITIES: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for ReleaseBatchPost + lazy_static! { + pub static ref RELEASE_BATCH_POST_BAD_REQUEST: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for ReleaseBatchPost + lazy_static! { + pub static ref RELEASE_BATCH_POST_NOT_FOUND: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for ReleaseBatchPost + lazy_static! { + pub static ref RELEASE_BATCH_POST_GENERIC_ERROR: Mime = mime!(Application / Json); + } /// Create Mime objects for the response content types for ReleaseIdGet lazy_static! { pub static ref RELEASE_ID_GET_FOUND_ENTITY: Mime = mime!(Application / Json); @@ -264,6 +328,22 @@ pub mod responses { lazy_static! { pub static ref RELEASE_POST_GENERIC_ERROR: Mime = mime!(Application / Json); } + /// Create Mime objects for the response content types for WorkBatchPost + lazy_static! { + pub static ref WORK_BATCH_POST_CREATED_ENTITIES: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for WorkBatchPost + lazy_static! { + pub static ref WORK_BATCH_POST_BAD_REQUEST: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for WorkBatchPost + lazy_static! { + pub static ref WORK_BATCH_POST_NOT_FOUND: Mime = mime!(Application / Json); + } + /// Create Mime objects for the response content types for WorkBatchPost + lazy_static! { + pub static ref WORK_BATCH_POST_GENERIC_ERROR: Mime = mime!(Application / Json); + } /// Create Mime objects for the response content types for WorkIdGet lazy_static! { pub static ref WORK_ID_GET_FOUND_ENTITY: Mime = mime!(Application / Json); @@ -301,10 +381,18 @@ pub mod responses { pub mod requests { use hyper::mime::*; + /// Create Mime objects for the request content types for ContainerBatchPost + lazy_static! { + pub static ref CONTAINER_BATCH_POST: Mime = mime!(Application / Json); + } /// Create Mime objects for the request content types for ContainerPost lazy_static! { pub static ref CONTAINER_POST: Mime = mime!(Application / Json); } + /// Create Mime objects for the request content types for CreatorBatchPost + lazy_static! { + pub static ref CREATOR_BATCH_POST: Mime = mime!(Application / Json); + } /// Create Mime objects for the request content types for CreatorPost lazy_static! { pub static ref CREATOR_POST: Mime = mime!(Application / Json); @@ -313,14 +401,26 @@ pub mod requests { lazy_static! { pub static ref EDITGROUP_POST: Mime = mime!(Application / Json); } + /// Create Mime objects for the request content types for FileBatchPost + lazy_static! { + pub static ref FILE_BATCH_POST: Mime = mime!(Application / Json); + } /// Create Mime objects for the request content types for FilePost lazy_static! { pub static ref FILE_POST: Mime = mime!(Application / Json); } + /// Create Mime objects for the request content types for ReleaseBatchPost + lazy_static! { + pub static ref RELEASE_BATCH_POST: Mime = mime!(Application / Json); + } /// Create Mime objects for the request content types for ReleasePost lazy_static! { pub static ref RELEASE_POST: Mime = mime!(Application / Json); } + /// Create Mime objects for the request content types for WorkBatchPost + lazy_static! { + pub static ref WORK_BATCH_POST: Mime = mime!(Application / Json); + } /// Create Mime objects for the request content types for WorkPost lazy_static! { pub static ref WORK_POST: Mime = mime!(Application / Json); diff --git a/rust/fatcat-api/src/models.rs b/rust/fatcat-api/src/models.rs index 24c66f6b..ab18e9b3 100644 --- a/rust/fatcat-api/src/models.rs +++ b/rust/fatcat-api/src/models.rs @@ -113,30 +113,30 @@ pub struct ContainerEntity { #[serde(rename = "name")] pub name: String, - // Note: inline enums are not fully supported by swagger-codegen - #[serde(rename = "state")] - #[serde(skip_serializing_if = "Option::is_none")] - pub state: Option, - - #[serde(rename = "ident")] + #[serde(rename = "extra")] #[serde(skip_serializing_if = "Option::is_none")] - pub ident: Option, + pub extra: Option, - #[serde(rename = "revision")] + #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] - pub revision: Option, + pub editgroup_id: Option, #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] pub redirect: Option, - #[serde(rename = "editgroup_id")] + #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] - pub editgroup_id: Option, + pub revision: Option, - #[serde(rename = "extra")] + #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] - pub extra: Option, + pub ident: Option, + + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "state")] + #[serde(skip_serializing_if = "Option::is_none")] + pub state: Option, } impl ContainerEntity { @@ -147,12 +147,12 @@ impl ContainerEntity { issnl: None, publisher: None, name: name, - state: None, - ident: None, - revision: None, - redirect: None, - editgroup_id: None, extra: None, + editgroup_id: None, + redirect: None, + revision: None, + ident: None, + state: None, } } } @@ -166,30 +166,30 @@ pub struct CreatorEntity { #[serde(rename = "full_name")] pub full_name: String, - #[serde(rename = "extra")] - #[serde(skip_serializing_if = "Option::is_none")] - pub extra: Option, - - #[serde(rename = "editgroup_id")] + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "state")] #[serde(skip_serializing_if = "Option::is_none")] - pub editgroup_id: Option, + pub state: Option, - #[serde(rename = "redirect")] + #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] - pub redirect: Option, + pub ident: Option, #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] pub revision: Option, - #[serde(rename = "ident")] + #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] - pub ident: Option, + pub redirect: Option, - // Note: inline enums are not fully supported by swagger-codegen - #[serde(rename = "state")] + #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] - pub state: Option, + pub editgroup_id: Option, + + #[serde(rename = "extra")] + #[serde(skip_serializing_if = "Option::is_none")] + pub extra: Option, } impl CreatorEntity { @@ -197,12 +197,12 @@ impl CreatorEntity { CreatorEntity { orcid: None, full_name: full_name, - extra: None, - editgroup_id: None, - redirect: None, - revision: None, - ident: None, state: None, + ident: None, + revision: None, + redirect: None, + editgroup_id: None, + extra: None, } } } diff --git a/rust/fatcat-api/src/server.rs b/rust/fatcat-api/src/server.rs index 7fdc5d2a..0db2c445 100644 --- a/rust/fatcat-api/src/server.rs +++ b/rust/fatcat-api/src/server.rs @@ -36,9 +36,10 @@ 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}; +use {Api, ContainerBatchPostResponse, ContainerIdGetResponse, ContainerLookupGetResponse, ContainerPostResponse, CreatorBatchPostResponse, CreatorIdGetResponse, CreatorLookupGetResponse, + CreatorPostResponse, EditgroupIdAcceptPostResponse, EditgroupIdGetResponse, EditgroupPostResponse, EditorUsernameChangelogGetResponse, EditorUsernameGetResponse, FileBatchPostResponse, + FileIdGetResponse, FileLookupGetResponse, FilePostResponse, ReleaseBatchPostResponse, ReleaseIdGetResponse, ReleaseLookupGetResponse, ReleasePostResponse, WorkBatchPostResponse, + WorkIdGetResponse, WorkPostResponse}; header! { (Warning, "Warning") => [String] } @@ -85,6 +86,112 @@ fn add_routes(router: &mut Router, api: T) where T: Api + Send + Sync + Clone + 'static, { + let api_clone = api.clone(); + router.post( + "/v0/container/batch", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result + where + T: Api, + { + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + // 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. + + let param_entity_list = req.get::() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + + let param_entity_list: Option> = + serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + + param_entity_list + } else { + None + }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + + match api.container_batch_post(param_entity_list.as_ref(), context).wait() { + Ok(rsp) => match rsp { + ContainerBatchPostResponse::CreatedEntities(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CONTAINER_BATCH_POST_CREATED_ENTITIES.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + ContainerBatchPostResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::CONTAINER_BATCH_POST_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + ContainerBatchPostResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::CONTAINER_BATCH_POST_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + ContainerBatchPostResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(0), body_string)); + response.headers.set(ContentType(mimetypes::responses::CONTAINER_BATCH_POST_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "ContainerBatchPost", + ); + let api_clone = api.clone(); router.get( "/v0/container/:id", @@ -363,6 +470,112 @@ where "ContainerPost", ); + let api_clone = api.clone(); + router.post( + "/v0/creator/batch", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result + where + T: Api, + { + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + // 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. + + let param_entity_list = req.get::() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + + let param_entity_list: Option> = + serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + + param_entity_list + } else { + None + }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + + match api.creator_batch_post(param_entity_list.as_ref(), context).wait() { + Ok(rsp) => match rsp { + CreatorBatchPostResponse::CreatedEntities(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATOR_BATCH_POST_CREATED_ENTITIES.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + CreatorBatchPostResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATOR_BATCH_POST_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + CreatorBatchPostResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATOR_BATCH_POST_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + CreatorBatchPostResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(0), body_string)); + response.headers.set(ContentType(mimetypes::responses::CREATOR_BATCH_POST_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "CreatorBatchPost", + ); + let api_clone = api.clone(); router.get( "/v0/creator/:id", @@ -1066,6 +1279,112 @@ where "EditorUsernameGet", ); + let api_clone = api.clone(); + router.post( + "/v0/file/batch", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result + where + T: Api, + { + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + // 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. + + let param_entity_list = req.get::() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + + let param_entity_list: Option> = + serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + + param_entity_list + } else { + None + }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + + match api.file_batch_post(param_entity_list.as_ref(), context).wait() { + Ok(rsp) => match rsp { + FileBatchPostResponse::CreatedEntities(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::FILE_BATCH_POST_CREATED_ENTITIES.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + FileBatchPostResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::FILE_BATCH_POST_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + FileBatchPostResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::FILE_BATCH_POST_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + FileBatchPostResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(0), body_string)); + response.headers.set(ContentType(mimetypes::responses::FILE_BATCH_POST_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FileBatchPost", + ); + let api_clone = api.clone(); router.get( "/v0/file/:id", @@ -1344,6 +1663,112 @@ where "FilePost", ); + let api_clone = api.clone(); + router.post( + "/v0/release/batch", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result + where + T: Api, + { + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + // 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. + + let param_entity_list = req.get::() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + + let param_entity_list: Option> = + serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + + param_entity_list + } else { + None + }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + + match api.release_batch_post(param_entity_list.as_ref(), context).wait() { + Ok(rsp) => match rsp { + ReleaseBatchPostResponse::CreatedEntities(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::RELEASE_BATCH_POST_CREATED_ENTITIES.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + ReleaseBatchPostResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::RELEASE_BATCH_POST_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + ReleaseBatchPostResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::RELEASE_BATCH_POST_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + ReleaseBatchPostResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(0), body_string)); + response.headers.set(ContentType(mimetypes::responses::RELEASE_BATCH_POST_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "ReleaseBatchPost", + ); + let api_clone = api.clone(); router.get( "/v0/release/:id", @@ -1622,6 +2047,112 @@ where "ReleasePost", ); + let api_clone = api.clone(); + router.post( + "/v0/work/batch", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result + where + T: Api, + { + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + // 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. + + let param_entity_list = req.get::() + .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - not valid UTF-8: {}", e))))?; + + let mut unused_elements = Vec::new(); + + let param_entity_list = if let Some(param_entity_list_raw) = param_entity_list { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_entity_list_raw); + + let param_entity_list: Option> = + serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter entity_list - doesn't match schema: {}", e))))?; + + param_entity_list + } else { + None + }; + let param_entity_list = param_entity_list.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter entity_list".to_string())))?; + + match api.work_batch_post(param_entity_list.as_ref(), context).wait() { + Ok(rsp) => match rsp { + WorkBatchPostResponse::CreatedEntities(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(201), body_string)); + response.headers.set(ContentType(mimetypes::responses::WORK_BATCH_POST_CREATED_ENTITIES.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + WorkBatchPostResponse::BadRequest(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(400), body_string)); + response.headers.set(ContentType(mimetypes::responses::WORK_BATCH_POST_BAD_REQUEST.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + WorkBatchPostResponse::NotFound(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(404), body_string)); + response.headers.set(ContentType(mimetypes::responses::WORK_BATCH_POST_NOT_FOUND.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + WorkBatchPostResponse::GenericError(body) => { + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(0), body_string)); + response.headers.set(ContentType(mimetypes::responses::WORK_BATCH_POST_GENERIC_ERROR.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + } + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "WorkBatchPost", + ); + let api_clone = api.clone(); router.get( "/v0/work/:id", -- cgit v1.2.3