Matching expressions

We have to reorganize the code of microservice_handler because we can't use regular expressions in a match expression. We have to extract the method with the path at the start, because we need it for most responses:

let response = {
let method = req.method();
let path = req.uri().path();
let mut users = user_db.lock().unwrap();

// Put regular expressions here
};
futures::ok()

The first thing we'll check is the index page requests. Add the following code:

if INDEX_PATH.is_match(path) {
if method == &Method::GET {
Response::new(INDEX.into())
} else {
response_with_code(StatusCode::METHOD_NOT_ALLOWED)
}

This uses the INDEX_PATH regular expression to check whether the request's path matches the index page request using the Regex::is_match method, which returns a bool value. Here, we're checking the method of a request, so only GET is allowed.

We'll then continue the if clause with an alternative condition for the user list request:

} else if USERS_PATH.is_match(path) {
if method == &Method::GET {
let list = users.iter()
.map(|(id, _)| id.to_string())
.collect::<Vec<String>>()
.join(",");
Response::new(list.into())
} else {
response_with_code(StatusCode::METHOD_NOT_ALLOWED)
}

This code uses the USERS_PATH pattern to check whether the client requested the list of users. This is a new path route. After this, we iterate over all the users in the database and join their IDs in a single string.

The following code is used to handle REST requests:

} else if let Some(cap) = USER_PATH.captures(path) {
let user_id = cap.name("user_id").and_then(|m| {
m.as_str()
.parse::<UserId>()
.ok()
.map(|x| x as usize)
});
// Put match expression with (method, user_id) tuple

This code uses the USER_PATH and the Regex::captures method. It returns a Captures object with the values of all captured groups. If the pattern doesn't match the method, it returns a None value. If the pattern does match, we get an object stored in the cap variable. The Captures struct has the name method to get a captured value by name. We use the user_id as the name of the group. This group can be optional and the name method returns an Option. We use the and_then method of the Option to replace it with the parsed UserId. Finally, the user_id variable takes the Option<UserId> value, in the same way as the previous version of our microservice. To avoid repetition, I skipped the block where the request is the same as the (method, user_id) tuple  just copy this part from the example in the previous section of this chapter.

 

The last part is a default handler that returns a response with a NOT_FOUND status code:

} else {
response_with_code(StatusCode::NOT_FOUND)
}

The service is now complete, so it can be compiled and run. In Chapter 13, Testing and Debugging Rust Microservices, you'll find out how to debug microservices. For now, however, you can use the curl command to send some POST requests and check the result in the browser. Type the following command in the shell to add three users and remove the second user with the ID of 1:

$ curl -X POST http://localhost:8080/user/
0
$ curl -X POST http://localhost:8080/user/
1
$ curl -X POST http://localhost:8080/user/
2
$ curl -X DELETE http://localhost:8080/user/1
$ curl http://localhost:8080/users
0,2

If you fetch the list of users in the browser, it should display the following:

As you can see, we used the /users request without a trailing slash with curl, and /users/ with the trailing slash in the browser. This result means that regular expressions and request routing both work.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.189.251