Skip to content

Commit

Permalink
Iotedged: Encode deviceId/moduleId for IOThub operations (#750)
Browse files Browse the repository at this point in the history
* Add url encoding

* Cleanup

* Add test

* Use percent encoding

* Fix test

* Fixing formatting

* Remove println

* Remove tostring.. return PercentEncode<T> instead
  • Loading branch information
varunpuranik authored Jan 30, 2019
1 parent 4992833 commit bb10be0
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 4 deletions.
1 change: 1 addition & 0 deletions edgelet/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions edgelet/iothubservice/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ publish = false
failure = "0.1"
futures = "0.1"
hyper = "0.12"
percent-encoding = "1.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
Expand Down
76 changes: 72 additions & 4 deletions edgelet/iothubservice/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ use failure::{Fail, ResultExt};
use futures::future::{self, Either};
use futures::Future;
use hyper::{Method, StatusCode};
use percent_encoding::{percent_encode, PercentEncode, PATH_SEGMENT_ENCODE_SET};

use edgelet_http::client::{Client, ClientImpl, TokenSource};
use edgelet_http::error::ErrorKind as HttpErrorKind;
use edgelet_utils::ensure_not_empty_with_context;
use error::{Error, ErrorKind, ModuleOperationReason};
use model::{AuthMechanism, Module};

define_encode_set! {
pub IOTHUB_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | { '=' }
}

pub struct DeviceClient<C, T> {
client: Client<C, T>,
device_id: String,
Expand Down Expand Up @@ -81,7 +86,11 @@ where
.client
.request::<Module, Module>(
Method::PUT,
&format!("/devices/{}/modules/{}", &self.device_id, module_id),
&format!(
"/devices/{}/modules/{}",
url_encode(&self.device_id),
url_encode(&module_id)
),
None,
Some(module),
add_if_match,
Expand Down Expand Up @@ -113,7 +122,11 @@ where
.client
.request::<(), Module>(
Method::GET,
&format!("/devices/{}/modules/{}", &self.device_id, module_id),
&format!(
"/devices/{}/modules/{}",
url_encode(&self.device_id),
url_encode(&module_id)
),
None,
None,
false,
Expand Down Expand Up @@ -148,7 +161,7 @@ where
self.client
.request::<(), Vec<Module>>(
Method::GET,
&format!("/devices/{}/modules", &self.device_id),
&format!("/devices/{}/modules", url_encode(&self.device_id)),
None,
None,
false,
Expand All @@ -174,7 +187,11 @@ where
.client
.request::<(), ()>(
Method::DELETE,
&format!("/devices/{}/modules/{}", self.device_id, module_id),
&format!(
"/devices/{}/modules/{}",
url_encode(&self.device_id),
url_encode(&module_id)
),
None,
None,
true,
Expand All @@ -200,6 +217,10 @@ where
}
}

fn url_encode(value: &str) -> PercentEncode<'_, IOTHUB_ENCODE_SET> {
percent_encode(value.as_bytes(), IOTHUB_ENCODE_SET)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -636,6 +657,53 @@ mod tests {
.unwrap();
}

#[test]
fn modules_get_request_with_encoding() {
let api_version = "2018-04-10".to_string();
let host_name = Url::parse("http://localhost").unwrap();
let auth = AuthMechanism::default()
.with_type(AuthType::Sas)
.with_symmetric_key(
SymmetricKey::default()
.with_primary_key("pkey".to_string())
.with_secondary_key("skey".to_string()),
);
let module = Module::default()
.with_device_id("[email protected]#st".to_string())
.with_module_id("$edgeAgent".to_string())
.with_generation_id("g1".to_string())
.with_managed_by("iotedge".to_string())
.with_authentication(auth.clone());
let expected_module = module.clone();

let handler = move |req: Request<Body>| {
assert_eq!(req.method(), &Method::GET);
assert_eq!(req.uri().path(), "/devices/[email protected]%23st/modules/$edgeAgent");
assert_eq!(None, req.headers().get(hyper::header::IF_MATCH));

let mut response = Response::new(serde_json::to_string(&module).unwrap().into());
response
.headers_mut()
.typed_insert(&ContentType(mime::APPLICATION_JSON));
Ok(response)
};
let client = Client::new(handler, Some(NullTokenSource), api_version, host_name).unwrap();

let device_client = DeviceClient::new(client, "[email protected]#st".to_string()).unwrap();
let task = device_client
.get_module_by_id("$edgeAgent".to_string())
.then(|module| {
let module = module.unwrap();
assert_eq!(expected_module, module);
Ok::<_, Error>(())
});

tokio::runtime::current_thread::Runtime::new()
.unwrap()
.block_on(task)
.unwrap();
}

#[test]
fn modules_get_not_found() {
let api_version = "2018-04-10".to_string();
Expand Down
2 changes: 2 additions & 0 deletions edgelet/iothubservice/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ extern crate failure;
extern crate futures;
extern crate hyper;
#[macro_use]
extern crate percent_encoding;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(test)]
Expand Down

0 comments on commit bb10be0

Please sign in to comment.