REST API with Rust + Warp 5: Beyond test utilities
Tags: rust, warp, rest, api
Published: 2021-04-14 12:21:44

Last part, folks!

-----

## Time to say goodbye. Warp 5.

> The code for this part is available [here](https://github.com/rogertorres/dev.to/tree/main/warp/warp5).

Warp's test utilities are great, but I didn't want to end this series without actually being able to serve what has been built and to `curl` against it.

To do so, I first created a `/src/bin/main.rs` file. Then, I changed `Cargo.toml` to add this:

```toml
[[bin]]
name = "holodeck"
path = "src/bin/main.rs"

[lib]
name = "holodeck"
path = "src/lib.rs"
```

As I mentioned at the beginning, it is easier to find examples of code serving and consuming the API than testing it using the test utilities; so I'm gonna fly over it.

My `main.rs` ended up like this:

```rust
// I made "models" and "filters" public in lib.rs
use holodeck::{ models, filters };
use warp::Filter;

#[tokio::main]
async fn main() {

    let db = models::new_db();
    let routes = filters::list_sims(db.clone())
        .or(filters::post_sim(db.clone()))
        .or(filters::update_sim(db.clone()))
        .or(filters::delete_sim(db));

    warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
```

And that's all! I just had to put the filters together using `or` and serve. The clones work because we're cloning an `Arc`, which doesn't create a new copy, just a new reference to our `Mutex`.

Below you will find some some `curl`s I made.

`POST`
```
curl --location --request POST 'localhost:3030/holodeck' \
--header 'Content-Type: application/json' \
--header 'Content-Type: text/plain' \
--data-raw '{
    "id": 1,
    "name": "The Big Goodbye"
}'

curl --location --request POST 'localhost:3030/holodeck' \
--header 'Content-Type: application/json' \
--header 'Content-Type: text/plain' \
--data-raw '{
    "id": 2,
    "name": "Bride Of Chaotica!"
}'
```

`PUT`
```
curl --location --request PUT 'localhost:3030/holodeck/3' \
--header 'Content-Type: application/json' \
--header 'Content-Type: text/plain' \
--data-raw '{
    "name": "A Fistful Of Datas"
}'

curl --location --request PUT 'localhost:3030/holodeck/3' \
--header 'Content-Type: application/json' \
--header 'Content-Type: text/plain' \
--data-raw '{
    "name": "A Fistful Of La Forges"
}'
```

`GET`
```
curl --location --request GET 'localhost:3030/holodeck'

curl --location --request GET 'localhost:3030/holodeck/2'
```

`DELETE`
```
curl --location --request DELETE 'localhost:3030/holodeck/1' 
```

The good thing about using warp's test utilities is that when the time comes to serve what you built, there's no extra effort; no refactoring. So if you are using the tests, I strongly advise you to try some `curl`s as well. Here are some problems that I just found when doing it:
- At some point, I deleted the `warp::get()` from my `list_sims()` and as a result answering every request I made;
- The serialization/deserialization in `PUT` wasn't working properly. As this didn't appear in the tests, I assumed `serde` was being so good at its job the ended up hiding a mistake I made in the code.
- Delete reply had the right Status, but the wrong written message.

-----

## The End

What a journey! I really hope it ends up being useful to someone else.

Before letting you go, I would like to write a small _mea culpa_, to warn you about the things that are not ok regarding what was built here.

My main goal was to show the **process**, not the result; I didn't want to post a finished code and write a text explaining it. Although I am happy with this choice, it has some drawbacks. To make things clearer, I avoided creating and using too many functions that would compel the reader to check the previous code to make sense of it. So be aware that these things are not ok:
- Code repetition is problem number one. Tests are creating the same Simulations, there are repeated `use` keywords everywhere and so on;
- I forced the HashMap, so it never felt "natural". I don't regret it because it gave me a chance to show you the trait implementation, but oftentimes it was a bit of a hassle;
- Warp provides building blocks, which means that there is more than one way of doing the same things, and naturally, some are better than others. I didn't stress this much, often going with the easiest way;
- The tests are *far away* from actually checking everything that should be checked.

And I think that's enough. Really! Thank you for spending the time.

_**Live long and prosper!**_

🖖