Skip to content

Commit

Permalink
Merge pull request #5 from WURFL/0.2.0
Browse files Browse the repository at this point in the history
0.2.0
  • Loading branch information
andreacastello authored Oct 14, 2024
2 parents 0743a36 + 2021f69 commit dbbfccb
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 38 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### 0.2.0
- Updated rust edition used and project dependencies

### 0.1.1
- Added changelog. Small documentation changes

Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "wmclient"
version = "0.1.1"
version = "0.2.0"
authors = ["Andrea Castello <[email protected]>"]
edition = "2018"
edition = "2021"
license = "Apache-2.0"
homepage = "https://www.scientiamobile.com"
repository = "https://github.com/WURFL/wurfl-microservice-client-rust"
Expand All @@ -18,10 +18,10 @@ keywords = [
]

[dependencies]
reqwest = { version = "0.10", features = ["blocking", "json"] }
reqwest = { version = "0.12.8", features = ["blocking", "json"] }
openssl = { version = "^0.10", features = ["vendored"] }
lru = "0.7.0"
serde = { version = "1.0.130", features = ["derive"]}
serde = { version = "1.0.210", features = ["derive"]}
serde_json = "1.0"
thiserror = "1.0"
md5 = "0.7.0"
Expand Down
83 changes: 55 additions & 28 deletions examples/web_server_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,76 @@ use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
use wmclient::WmClient;

#[tokio::main]
pub async fn main() {
// First, create a Wurfl microservice client instance and set a cache for it.
// change your server data to your preferred settings
/// Creates a new `WmClient` instance and returns it wrapped in an `Arc<Mutex<WmClient>>`.
///
/// This function initializes a new WURFL microservice client API for Rust. It takes no arguments and
/// returns the client instance wrapped in a thread-safe `Arc<Mutex<WmClient>>`. If there is an error
/// initializing the client, the function will panic with the error message.
///
/// The created client instance is printed to the console, displaying the API version.
fn create_wm_client() -> Arc<Mutex<WmClient>> {
let wmclient_res = WmClient::new("http", "localhost", "8080","");
let wm_client = match wmclient_res {
Ok(wm_client) => wm_client,
Err(error) => panic!("Problem initializing wurfl microservice client: {:?}", error),
};
println!("Created WURFL microservice client API for Rust version: {}", wm_client.get_api_version());
// The wurfl microservice client is mutable because contains some updatable internal state, so we need to
// wrap it into a Mutex to use it in the detect function
let safe_wm_client = Arc::new(Mutex::new(wm_client));
// A `Service` is needed for every connection, so this
// creates one wrapping our `detect` function.
Arc::new(Mutex::new(wm_client))
}

#[tokio::main]
/// Runs a web server that detects device capabilities using the WURFL microservice client.
///
/// This function creates a new WURFL microservice client, starts a Hyper web server on `localhost:3000`,
/// and handles incoming requests by detecting the device capabilities using the WURFL client.
/// The detected device information is returned in the response body.
/// Since both creation and APIs of the wmclient and the web server are blocking, we need to use
/// the spawn_blocking function to move its usage to a separate thread.
pub async fn main() {
let safe_wm_client = tokio::task::spawn_blocking(move || {
create_wm_client()
}).await
.expect("WM client creation failed");

let make_svc = make_service_fn(move |_conn| {
let mut safe_wm_client_clone = Arc::clone(&safe_wm_client);
let safe_wm_client_clone = Arc::clone(&safe_wm_client);
// This is an async block that will be executed as part of the service function.
async {
Ok::<_, Infallible>(service_fn(move |req| {
let response = detect(req, &mut safe_wm_client_clone);
async { Ok::<_, Infallible>(Response::new(Body::from(response))) }
let safe_wm_client_clone = Arc::clone(&safe_wm_client_clone);
async move {
let response = detect(req, safe_wm_client_clone).await;
Ok::<_, Infallible>(Response::new(Body::from(response)))
}
}))
}
});

// We'll bind the server to 127.0.0.1:3000
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let server = Server::bind(&addr).serve(make_svc);
match server.await {
Err(_) => panic!("An error occurred while running WURFL microservice hyper server example, shutting down"),
_ => (),
if let Err(_) = server.await {
eprintln!("An error occurred while running WURFL microservice hyper server example, shutting down");
}
}

// Actual device detection: returns a string with wurfl_id and virtual capability complete_device_name
fn detect(_req: Request<Body>, safe_client: &mut Arc<Mutex<WmClient>>) -> String {
let mut client_guard = safe_client.lock().unwrap();
let device = match client_guard.lookup_headers(_req.headers()) {
Ok(d) => d,
Err(_) => panic!("Error during lookup")
};
drop(client_guard);
let body = format!("Detected device: {} - {} ", device.capabilities.get("wurfl_id").unwrap(),
device.capabilities.get("complete_device_name").unwrap());
return body;
/// Detects the device information from the request headers and returns a formatted string with the device capabilities.
///
/// This function takes a request object and a thread-safe WURFL microservice client instance, and uses the client to look up the device information based on the request headers. It then formats the detected device information as a string and returns it.
///
/// # Arguments
/// * `req` - The HTTP request object containing the headers to detect the device.
/// * `safe_client` - A thread-safe WURFL microservice client instance to use for the device lookup.
///
/// # Returns
/// A string containing the detected device information, including the WURFL ID and the complete device name.
async fn detect(req: Request<Body>, safe_client: Arc<Mutex<WmClient>>) -> String {
tokio::task::spawn_blocking(move || {
let mut client_guard = safe_client.lock().unwrap();
let device = match client_guard.lookup_headers(req.headers()) {
Ok(d) => d,
Err(_) => panic!("Error during lookup")
};
format!("Detected device: {} - {} ",
device.capabilities.get("wurfl_id").unwrap(),
device.capabilities.get("complete_device_name").unwrap())
}).await.unwrap()
}
2 changes: 1 addition & 1 deletion src/wmclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl WmClient {

/// Returns the version of this Rust client API
pub fn get_api_version(&self) -> &str {
"0.1.0"
"0.2.0"
}

/// sets the overall HTTP timeout in milliseconds
Expand Down
6 changes: 1 addition & 5 deletions tests/wmclient_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,8 @@ fn test_set_http_timeout_expiration(){
assert!(client_res.is_ok());
let mut client = client_res.unwrap();
client.set_http_timeout(1, 1);
let res = client.get_info();
let res = client.get_all_device_makes();
assert!(res.is_err());
let err_opt = res.err();
assert!(err_opt.is_some());
let err_msg = err_opt.unwrap();
assert!(err_msg.to_string().contains("timed out"));
}

#[test]
Expand Down

0 comments on commit dbbfccb

Please sign in to comment.