Implement various kinds of error handling and resource management.
An important point of programming is how to handle errors and close resources even if errors occur.
This exercise requires you to handle various errors. Because error handling is rather programming language specific you'll have to refer to the tests for your track to see what's exactly required.
You are building a tiny web server that queries an even tinier user database. Sounds easy, but in the real world many things can (and often do) go wrong:
"https://"
"example.com"
"https://example.com/"
, "https://example.com/users/"
and "https://example.com/users/<userId>"
are alloweduserId
may not be a positive integeruserId
When things go wrong, it's important to give the end user a nice and helpful error message so that they can solve the issue. For this, you need to ensure that your code propagates informative errors from the point where the error is detected to the point where the error message is produced.
Luckily, Roc allows you to carry payload (i.e., data) inside your Err
tag. It's tempting to carry an error message directly (e.g., Err "User #42 was not found"
), and this may be fine in some simple cases, but this has several limitations:
Str.toU64
function can be used to parse all sorts of integers: days, seconds, user IDs, and more. If the error message just says Could not convert string "0.5" to a positive integer
, the user may not have enough context to solve the issue.So in this exercise, your errors will instead carry a meaningful tag along with its own helpful payload. For example, if the user is not found, the error will look like Err (UserNotFound 42)
.
Okay, let's get started! Here's what you need to do:
getUser
to return the requested user from the users
"database" (it's actually just a Dict
). Make sure the function returns Err (UserNotFound userId)
in case the user is not found, instead of Err KeyNotFound
.parseUserId
to convert the URL's path (such as "/users/123"
) to a positive integer user ID (123
). In case of error, return Err (InvalidUserId userIdStr)
.getPage
:
"https://example.com/"
, return Ok "Home page"
"https://example.com/users/"
, return Ok "Users page"
"https://example.com/users/<userId>"
, parse the user ID, load the user with that ID, and return Ok "<user name>'s page"
"https://"
, return Err (InsecureConnection url)
"example.com"
, return Err (InvalidDomain url)
/
or /users/
or /users/<user id>
, return Err (PageNotFound path)
Err (InvalidUserId userIdStr)
Err (UserNotFound userId)
errorMessage
to convert the previous errors to translated error messages. The function should at least handle English, but you are encouraged to try handling another language as well. The English error messages should like this:"Insecure connection (non HTTPS): http://example.com/users/789"
"Invalid domain name: https://google.com/wrong"
"Page not found: /oops"
"User ID is not a positive integer: abc"
"User #42 was not found"
Note: instead of displaying an error message to the user when they use HTTP instead of HTTPS, your web server could redirect their browser to HTTPS, and the user would not even notice the error. Since the errors are machine-friendly in Roc, this would be very easy to implement.
Sign up to Exercism to learn and master Roc with 105 exercises, and real human mentoring, all for free.