diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2018-07-25 23:40:28 -0700 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2018-07-25 23:40:28 -0700 |
commit | 10e59ac5d002c0b91dece34ed2a082ba5f022edd (patch) | |
tree | 25f8ccd3641060315eb65534dfb286edf5e36b59 /rust/fatcat-api/src | |
parent | 5b8d98192972ccbc776024dc4041e4519557a03b (diff) | |
download | fatcat-10e59ac5d002c0b91dece34ed2a082ba5f022edd.tar.gz fatcat-10e59ac5d002c0b91dece34ed2a082ba5f022edd.zip |
API schema: identifier checking, expand query param
Diffstat (limited to 'rust/fatcat-api/src')
-rw-r--r-- | rust/fatcat-api/src/client.rs | 60 | ||||
-rw-r--r-- | rust/fatcat-api/src/lib.rs | 40 | ||||
-rw-r--r-- | rust/fatcat-api/src/models.rs | 40 | ||||
-rw-r--r-- | rust/fatcat-api/src/server.rs | 30 |
4 files changed, 135 insertions, 35 deletions
diff --git a/rust/fatcat-api/src/client.rs b/rust/fatcat-api/src/client.rs index 2b6fd2a6..10d4287d 100644 --- a/rust/fatcat-api/src/client.rs +++ b/rust/fatcat-api/src/client.rs @@ -1035,8 +1035,16 @@ impl Api for Client { Box::new(futures::done(result)) } - fn get_container(&self, param_id: String, context: &Context) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send> { - let url = format!("{}/v0/container/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); + fn get_container(&self, param_id: String, param_expend: Option<String>, context: &Context) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send> { + // Query parameters + let query_expend = param_expend.map_or_else(String::new, |query| format!("expend={expend}&", expend = query.to_string())); + + let url = format!( + "{}/v0/container/{id}?{expend}", + self.base_path, + id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET), + expend = utf8_percent_encode(&query_expend, QUERY_ENCODE_SET) + ); let hyper_client = (self.hyper_client)(); let request = hyper_client.request(hyper::method::Method::Get, &url); @@ -1163,8 +1171,16 @@ impl Api for Client { Box::new(futures::done(result)) } - fn get_creator(&self, param_id: String, context: &Context) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send> { - let url = format!("{}/v0/creator/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); + fn get_creator(&self, param_id: String, param_expend: Option<String>, context: &Context) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send> { + // Query parameters + let query_expend = param_expend.map_or_else(String::new, |query| format!("expend={expend}&", expend = query.to_string())); + + let url = format!( + "{}/v0/creator/{id}?{expend}", + self.base_path, + id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET), + expend = utf8_percent_encode(&query_expend, QUERY_ENCODE_SET) + ); let hyper_client = (self.hyper_client)(); let request = hyper_client.request(hyper::method::Method::Get, &url); @@ -1517,8 +1533,16 @@ impl Api for Client { Box::new(futures::done(result)) } - fn get_file(&self, param_id: String, context: &Context) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send> { - let url = format!("{}/v0/file/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); + fn get_file(&self, param_id: String, param_expend: Option<String>, context: &Context) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send> { + // Query parameters + let query_expend = param_expend.map_or_else(String::new, |query| format!("expend={expend}&", expend = query.to_string())); + + let url = format!( + "{}/v0/file/{id}?{expend}", + self.base_path, + id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET), + expend = utf8_percent_encode(&query_expend, QUERY_ENCODE_SET) + ); let hyper_client = (self.hyper_client)(); let request = hyper_client.request(hyper::method::Method::Get, &url); @@ -1645,8 +1669,16 @@ impl Api for Client { Box::new(futures::done(result)) } - fn get_release(&self, param_id: String, context: &Context) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send> { - let url = format!("{}/v0/release/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); + fn get_release(&self, param_id: String, param_expend: Option<String>, context: &Context) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send> { + // Query parameters + let query_expend = param_expend.map_or_else(String::new, |query| format!("expend={expend}&", expend = query.to_string())); + + let url = format!( + "{}/v0/release/{id}?{expend}", + self.base_path, + id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET), + expend = utf8_percent_encode(&query_expend, QUERY_ENCODE_SET) + ); let hyper_client = (self.hyper_client)(); let request = hyper_client.request(hyper::method::Method::Get, &url); @@ -1882,8 +1914,16 @@ impl Api for Client { Box::new(futures::done(result)) } - fn get_work(&self, param_id: String, context: &Context) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send> { - let url = format!("{}/v0/work/{id}", self.base_path, id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET)); + fn get_work(&self, param_id: String, param_expend: Option<String>, context: &Context) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send> { + // Query parameters + let query_expend = param_expend.map_or_else(String::new, |query| format!("expend={expend}&", expend = query.to_string())); + + let url = format!( + "{}/v0/work/{id}?{expend}", + self.base_path, + id = utf8_percent_encode(¶m_id.to_string(), PATH_SEGMENT_ENCODE_SET), + expend = utf8_percent_encode(&query_expend, QUERY_ENCODE_SET) + ); let hyper_client = (self.hyper_client)(); let request = hyper_client.request(hyper::method::Method::Get, &url); diff --git a/rust/fatcat-api/src/lib.rs b/rust/fatcat-api/src/lib.rs index 47d23d04..c55d6eea 100644 --- a/rust/fatcat-api/src/lib.rs +++ b/rust/fatcat-api/src/lib.rs @@ -466,11 +466,11 @@ pub trait Api { fn get_changelog_entry(&self, id: i64, context: &Context) -> Box<Future<Item = GetChangelogEntryResponse, Error = ApiError> + Send>; - fn get_container(&self, id: String, context: &Context) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send>; + fn get_container(&self, id: String, expend: Option<String>, context: &Context) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send>; fn get_container_history(&self, id: String, limit: Option<i64>, context: &Context) -> Box<Future<Item = GetContainerHistoryResponse, Error = ApiError> + Send>; - fn get_creator(&self, id: String, context: &Context) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send>; + fn get_creator(&self, id: String, expend: Option<String>, context: &Context) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send>; fn get_creator_history(&self, id: String, limit: Option<i64>, context: &Context) -> Box<Future<Item = GetCreatorHistoryResponse, Error = ApiError> + Send>; @@ -482,11 +482,11 @@ pub trait Api { fn get_editor_changelog(&self, id: String, context: &Context) -> Box<Future<Item = GetEditorChangelogResponse, Error = ApiError> + Send>; - fn get_file(&self, id: String, context: &Context) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send>; + fn get_file(&self, id: String, expend: Option<String>, context: &Context) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send>; fn get_file_history(&self, id: String, limit: Option<i64>, context: &Context) -> Box<Future<Item = GetFileHistoryResponse, Error = ApiError> + Send>; - fn get_release(&self, id: String, context: &Context) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send>; + fn get_release(&self, id: String, expend: Option<String>, context: &Context) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send>; fn get_release_files(&self, id: String, context: &Context) -> Box<Future<Item = GetReleaseFilesResponse, Error = ApiError> + Send>; @@ -494,7 +494,7 @@ pub trait Api { fn get_stats(&self, more: Option<String>, context: &Context) -> Box<Future<Item = GetStatsResponse, Error = ApiError> + Send>; - fn get_work(&self, id: String, context: &Context) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send>; + fn get_work(&self, id: String, expend: Option<String>, context: &Context) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send>; fn get_work_history(&self, id: String, limit: Option<i64>, context: &Context) -> Box<Future<Item = GetWorkHistoryResponse, Error = ApiError> + Send>; @@ -539,11 +539,11 @@ pub trait ApiNoContext { fn get_changelog_entry(&self, id: i64) -> Box<Future<Item = GetChangelogEntryResponse, Error = ApiError> + Send>; - fn get_container(&self, id: String) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send>; + fn get_container(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send>; fn get_container_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetContainerHistoryResponse, Error = ApiError> + Send>; - fn get_creator(&self, id: String) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send>; + fn get_creator(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send>; fn get_creator_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetCreatorHistoryResponse, Error = ApiError> + Send>; @@ -555,11 +555,11 @@ pub trait ApiNoContext { fn get_editor_changelog(&self, id: String) -> Box<Future<Item = GetEditorChangelogResponse, Error = ApiError> + Send>; - fn get_file(&self, id: String) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send>; + fn get_file(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send>; fn get_file_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetFileHistoryResponse, Error = ApiError> + Send>; - fn get_release(&self, id: String) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send>; + fn get_release(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send>; fn get_release_files(&self, id: String) -> Box<Future<Item = GetReleaseFilesResponse, Error = ApiError> + Send>; @@ -567,7 +567,7 @@ pub trait ApiNoContext { fn get_stats(&self, more: Option<String>) -> Box<Future<Item = GetStatsResponse, Error = ApiError> + Send>; - fn get_work(&self, id: String) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send>; + fn get_work(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send>; fn get_work_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetWorkHistoryResponse, Error = ApiError> + Send>; @@ -654,16 +654,16 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().get_changelog_entry(id, &self.context()) } - fn get_container(&self, id: String) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send> { - self.api().get_container(id, &self.context()) + fn get_container(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetContainerResponse, Error = ApiError> + Send> { + self.api().get_container(id, expend, &self.context()) } fn get_container_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetContainerHistoryResponse, Error = ApiError> + Send> { self.api().get_container_history(id, limit, &self.context()) } - fn get_creator(&self, id: String) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send> { - self.api().get_creator(id, &self.context()) + fn get_creator(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetCreatorResponse, Error = ApiError> + Send> { + self.api().get_creator(id, expend, &self.context()) } fn get_creator_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetCreatorHistoryResponse, Error = ApiError> + Send> { @@ -686,16 +686,16 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().get_editor_changelog(id, &self.context()) } - fn get_file(&self, id: String) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send> { - self.api().get_file(id, &self.context()) + fn get_file(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetFileResponse, Error = ApiError> + Send> { + self.api().get_file(id, expend, &self.context()) } fn get_file_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetFileHistoryResponse, Error = ApiError> + Send> { self.api().get_file_history(id, limit, &self.context()) } - fn get_release(&self, id: String) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send> { - self.api().get_release(id, &self.context()) + fn get_release(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetReleaseResponse, Error = ApiError> + Send> { + self.api().get_release(id, expend, &self.context()) } fn get_release_files(&self, id: String) -> Box<Future<Item = GetReleaseFilesResponse, Error = ApiError> + Send> { @@ -710,8 +710,8 @@ impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { self.api().get_stats(more, &self.context()) } - fn get_work(&self, id: String) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send> { - self.api().get_work(id, &self.context()) + fn get_work(&self, id: String, expend: Option<String>) -> Box<Future<Item = GetWorkResponse, Error = ApiError> + Send> { + self.api().get_work(id, expend, &self.context()) } fn get_work_history(&self, id: String, limit: Option<i64>) -> Box<Future<Item = GetWorkHistoryResponse, Error = ApiError> + Send> { diff --git a/rust/fatcat-api/src/models.rs b/rust/fatcat-api/src/models.rs index d85a1bbd..61812dc2 100644 --- a/rust/fatcat-api/src/models.rs +++ b/rust/fatcat-api/src/models.rs @@ -65,18 +65,22 @@ pub struct ContainerEntity { #[serde(skip_serializing_if = "Option::is_none")] pub extra: Option<serde_json::Value>, + /// base32-encoded unique identifier #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] pub editgroup_id: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] pub redirect: Option<String>, + /// UUID (lower-case, dash-separated, hex-encoded 128-bit) #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] pub revision: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] pub ident: Option<String>, @@ -132,18 +136,22 @@ pub struct CreatorEntity { #[serde(skip_serializing_if = "Option::is_none")] pub state: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] pub ident: Option<String>, + /// UUID (lower-case, dash-separated, hex-encoded 128-bit) #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] pub revision: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] pub redirect: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] pub editgroup_id: Option<String>, @@ -173,10 +181,12 @@ impl CreatorEntity { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Editgroup { + /// base32-encoded unique identifier #[serde(rename = "id")] #[serde(skip_serializing_if = "Option::is_none")] pub id: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "editor_id")] pub editor_id: String, @@ -366,18 +376,22 @@ pub struct FileEntity { #[serde(skip_serializing_if = "Option::is_none")] pub extra: Option<serde_json::Value>, + /// base32-encoded unique identifier #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] pub editgroup_id: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] pub redirect: Option<String>, + /// UUID (lower-case, dash-separated, hex-encoded 128-bit) #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] pub revision: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] pub ident: Option<String>, @@ -433,6 +447,11 @@ pub struct ReleaseContrib { #[serde(skip_serializing_if = "Option::is_none")] pub creator_id: Option<String>, + /// Optional; GET-only + #[serde(rename = "creator")] + #[serde(skip_serializing_if = "Option::is_none")] + pub creator: Option<models::CreatorEntity>, + #[serde(rename = "raw_name")] #[serde(skip_serializing_if = "Option::is_none")] pub raw_name: Option<String>, @@ -451,6 +470,7 @@ impl ReleaseContrib { ReleaseContrib { index: None, creator_id: None, + creator: None, raw_name: None, extra: None, role: None, @@ -529,6 +549,16 @@ pub struct ReleaseEntity { #[serde(skip_serializing_if = "Option::is_none")] pub container_id: Option<String>, + /// Optional; GET-only + #[serde(rename = "files")] + #[serde(skip_serializing_if = "Option::is_none")] + pub files: Option<Vec<models::FileEntity>>, + + /// Optional; GET-only + #[serde(rename = "container")] + #[serde(skip_serializing_if = "Option::is_none")] + pub container: Option<models::ContainerEntity>, + #[serde(rename = "work_id")] #[serde(skip_serializing_if = "Option::is_none")] pub work_id: Option<String>, @@ -541,18 +571,22 @@ pub struct ReleaseEntity { #[serde(skip_serializing_if = "Option::is_none")] pub state: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] pub ident: Option<String>, + /// UUID (lower-case, dash-separated, hex-encoded 128-bit) #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] pub revision: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] pub redirect: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] pub editgroup_id: Option<String>, @@ -582,6 +616,8 @@ impl ReleaseEntity { release_status: None, release_type: None, container_id: None, + files: None, + container: None, work_id: None, title: title, state: None, @@ -705,18 +741,22 @@ pub struct WorkEntity { #[serde(skip_serializing_if = "Option::is_none")] pub extra: Option<serde_json::Value>, + /// base32-encoded unique identifier #[serde(rename = "editgroup_id")] #[serde(skip_serializing_if = "Option::is_none")] pub editgroup_id: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "redirect")] #[serde(skip_serializing_if = "Option::is_none")] pub redirect: Option<String>, + /// UUID (lower-case, dash-separated, hex-encoded 128-bit) #[serde(rename = "revision")] #[serde(skip_serializing_if = "Option::is_none")] pub revision: Option<String>, + /// base32-encoded unique identifier #[serde(rename = "ident")] #[serde(skip_serializing_if = "Option::is_none")] pub ident: Option<String>, diff --git a/rust/fatcat-api/src/server.rs b/rust/fatcat-api/src/server.rs index e94fd5ef..0b170f03 100644 --- a/rust/fatcat-api/src/server.rs +++ b/rust/fatcat-api/src/server.rs @@ -1495,7 +1495,11 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_container(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_expend = query_params.get("expend").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_container(param_id, param_expend, context).wait() { Ok(rsp) => match rsp { GetContainerResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); @@ -1675,7 +1679,11 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_creator(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_expend = query_params.get("expend").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_creator(param_id, param_expend, context).wait() { Ok(rsp) => match rsp { GetCreatorResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); @@ -2187,7 +2195,11 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_file(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_expend = query_params.get("expend").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_file(param_id, param_expend, context).wait() { Ok(rsp) => match rsp { GetFileResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); @@ -2367,7 +2379,11 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_release(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_expend = query_params.get("expend").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_release(param_id, param_expend, context).wait() { Ok(rsp) => match rsp { GetReleaseResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); @@ -2693,7 +2709,11 @@ where .map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter id: {}", e))))? }; - match api.get_work(param_id, context).wait() { + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::<UrlEncodedQuery>().unwrap_or_default(); + let param_expend = query_params.get("expend").and_then(|list| list.first()).and_then(|x| x.parse::<String>().ok()); + + match api.get_work(param_id, param_expend, context).wait() { Ok(rsp) => match rsp { GetWorkResponse::FoundEntity(body) => { let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); |