# Rust Web Development With Rocket

## Metadata
- Author: Karuna Murti
- Full Title: Rust Web Development With Rocket
- Category: #rust #computer-networking #webdev #api
## Highlights
- On the other hand, there are no class definitions, but you can easily define a data type, for example, a struct. After defining that data type, you can create a block to implement its methods. ([Location 371](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=371))
- Even though there is no inheritance, you can easily group objects by using traits. ([Location 373](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=373))
- Here are a few reasons why people would want to use the Rust language for creating web applications: Safety No garbage collection Speed Multithreading and asynchronous programming Statically typed ([Location 400](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=400))
- Rust is a memory-safe language because it has certain rules regarding how a programmer can write their code. For example, when the code is compiled, it checks the lifetime of a variable, and the compiler will show an error if another variable still tries to access the already out-of-scope data. ([Location 413](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=413))
- The problem with this language design choice is that garbage collection usually takes significant computing resources. ([Location 424](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=424))
- Rust takes a different approach called resource acquisition is initialization (RAII), which means an object is deallocated automatically as soon as it's out of scope. ([Location 430](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=430))
- The Rust language is a compiled language, so the compiler will convert the program into machine code, which a computer processor can execute. A compiled language usually runs faster than an interpreted language because, in an interpreted language, there is an overhead when the runtime binary interprets the program into native machine code. ([Location 443](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=443))
- The solution is to use a different technique called asynchronous programming, where a single thread is reused by different tasks without waiting for the first task to finish. ([Location 458](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=458))
- Rocket is a fairly simple web framework without many bells and whistles, such as database Object-relational mapping (ORM) or mailing systems. Programmers can extend Rocket's capabilities using other Rust crates, for example, by adding third-party logging or connecting to memory store applications. ([Location 1247](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1247))
- The Rocket web framework treats incoming HTTP requests as a life cycle. The first thing the web application does is checks and determines which function or functions will be able to handle the incoming request. This part is called routing. For example, if there's a GET/something incoming request, Rocket will check all the registered routes for matches. ([Location 1252](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1252))
- After routing, Rocket will perform the validation of the incoming request against types and guards declared in the first function. If the result does not match and the next route handling function is available, Rocket will continue validation against the next function until there are no more functions available to handle that incoming request. ([Location 1255](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1255))
- After validation, Rocket will then process with what the programmer wrote in the body of the function. ([Location 1258](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1258))
- Rocket will finally return a response, which contains the HTTP status, headers, and body. The request life cycle is then complete. ([Location 1261](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1261))
- To recap, the life cycle of a Rocket request is Routing → Validation → Processing → Response. ([Location 1263](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1263))
- In the building process, the Rocket application also manages various states. A state is a Rust object that can be accessed in a route handler. ([Location 1268](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1268))
- In the Rocket framework, the function that provides middleware functionality is called a fairing. For example, if we want to have a universally unique identifier (UUID) for every HTTP request for audit purposes, we first create a fairing that generates a random UUID and appends it to the request HTTP header. ([Location 1273](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1273))
- Here, we are telling the Rust compiler to use macros from the Rocket crate by using the #[macro_use] attribute. We can skip using that attribute, but that would mean we must specify use for every single macro that we are going to use. ([Location 1293](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1293))
- The 'a in the Rust language means that a variable has a 'a lifetime. The life span of a reference depends on many things. ([Location 1304](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1304))
- There are seven method-specific route attributes that we can use: get, put, post, delete, head, options, and patch. All of them correspond to their respective HTTP method name. ([Location 1313](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1313))
- We have created a function that will generate the main function because we used the #[launch] attribute. Inside the function, we built the Rocket and mounted the routes that have an index function to the "/" path. ([Location 1325](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1325))
- Then, there is the default built-in fairing, Shield. Shield works by injecting HTTP security and privacy headers to all responses by default. ([Location 1370](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1370))
- You can only put the route attribute in a free function and not in a method inside impl of a Struct. ([Location 1780](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1780))
- The enum has the GET, PUT, POST, DELETE, OPTIONS, HEAD, TRACE, CONNECT, and PATCH members, which all correspond to valid HTTP methods defined in RFCs (Request For Comments). ([Location 1786](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1786))
- It looks simple, right? Unfortunately, we still have to use the #[route...] attribute if we want to handle HTTP CONNECT or TRACE as there are no method-specific route attributes for these two methods. ([Location 1802](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1802))
- Inside the route attribute, we can see the URI. The URI parameter is a string that has two parts, the path and the query. The part before the question mark (?) is the path and the part after the question mark is the query. ([Location 1807](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1807))
- Both the path and the query can be divided into segments. The path is segmented by the slash (/), as in /segment1/segment2. The query is segmented by an ampersand (&), as in ?segment1&segment2. ([Location 1810](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1810))
- A segment can be static or dynamic. The static form is fixed, such as /static or ?static. The dynamic segment is defined inside angle brackets (<>), as in /<dynamic> or ?<dynamic>. ([Location 1814](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1814))
- There is another dynamic form in angle brackets but trailed with two full stops (..), as in /<dynamic..>. This dynamic form is called multiple segments. If a regular dynamic segment must implement the FromParam trait, multiple segments must implement the rocket::request::FromSegments trait. ([Location 1897](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1897))
- PathBuf is a type for representing a file path in the operating system. This implementation is very useful for serving a static file from the Rocket application. ([Location 1904](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1904))
- Just like a path, a query segment can be a static segment or dynamic segment (such as "?<query1>&<query2>") or can be in a multiple "?<query..> form. The multiple query form is called trailing parameters. Unlike the path, the query part does not have the ignored part, "?<_>", or ignored trailing parameters such as "?<_..>". ([Location 1927](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1927))
- The path and query segments in a URI can be grouped into three colors: static, partial, or wild. If all segments of the path are static, the path is called a static path. If all segments of the query are static, we say the query has a static color. If all segments of the path or query are dynamic, we call the path or query wild. The partial color is when a path or query has both static and dynamic segments. ([Location 1938](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1938))
- Another parameter we can use in a route is format. In requests with the HTTP method with a payload, such as POST, PUT, PATCH and DELETE, the HTTP request Content-Type is checked against the value of this parameter. ([Location 1990](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=1990))
- The data parameter in the route is for processing the request body. The data must be in a dynamic form such as a dynamic <something> URI segment. After that, the declared attribute must be included as a parameter in the function following the route attribute. ([Location 2073](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2073))
- The Iterator trait has the collect() method, which can be used to collect items into the collection. Sometimes, you have to use the ::<Type> turbofish in collect::<Type>() if the result type cannot be inferred by the compiler. ([Location 2318](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2318))
- Why do we use rocket::response::{self...} instead of rocket::response::{Result...}? If we return -> Result, we cannot use std::result::Result, which is a pretty ubiquitous type in Rust. ([Location 2392](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2392))
- There's a common pattern that we can observe when we implement the std::iter::Iterator trait and rocket::response::Builder, called the builder pattern. It's a pattern used to generate an instance by chaining methods. Take a look at the following example. We can then generate a Something instance by chaining the command, such as Something.new().func1().func2(): ([Location 2419](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2419))
- Orphan rules mean neither type nor impl are in our application or crate. For example, we cannot implement impl Responder for Iterator in our application. The reason is that Iterator is defined in the standard library, and Responder is defined in the Rocket crate. ([Location 2435](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2435))
- Notice that the struct has a nameless field. ([Location 2442](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2442))
- The first module is rocket::response::status, which has the following structs: Accepted, BadRequest, Conflict, Created, Custom, Forbidden, NoContent, NotFound, and Unauthorized ([Location 2505](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2505))
- An application should be able to handle an error that may occur anytime during processing. In a web application, the standardized way to return an error to a client is by using an HTTP status code. Rocket provides a way to handle returning errors to clients in the form of rocket::Catcher. ([Location 2693](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2693))
- The function handling an error can have zero, one, or two parameters. If the function has one parameter, the parameter type must be &rocket::Request. If the function has two parameters, the first parameter type must be rocket::http::Status and the second parameter must be &Request. ([Location 2729](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2729))
- Another common feature in a web application is middleware. In this chapter, we will discuss two Rocket features (state and fairings), which act as the reusable object management and middleware parts of Rocket. ([Location 2788](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2788))
- In a web application, usually, programmers need to create an object that can be reused during the request/response life cycle. In the Rocket web framework, that object is called a state. A state can be anything such as a database connection pool, an object to store various customer statistics, an object to store a connection to a memory store, a client to send Simple Mail Transfer Protocol (SMTP) emails, and many more. ([Location 2807](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2807))
- We can tell Rocket to maintain the state, and this is called a managed state. ([Location 2811](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2811))
- The Rust language has traits and memory containers to solve syncing problems depending on how programmers intended the application to work. ([Location 2832](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2832))
- The solution is to create different containers for different use cases. These include std::cell::Rc and std::box::Box, among others. ([Location 2838](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2838))
- std::marker::Send is one of those traits. The Send trait is making sure any T type is safe to be transferred to another thread. Almost all types in the std library are Send, with a few exceptions such as std::rc::Rc and std::cell::UnsafeCell. Rc is a single-threaded reference counted pointer. ([Location 2840](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2840))
- Meanwhile, std::marker::Sync is saying the T type is safe to be shared across multiple threads. ([Location 2846](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2846))
- Both Send + Sync are marker traits; they don't have a function to be implemented by a type. They are also unsafe traits, so all types implementing these manually are also unsafe and can lead to undefined behavior. ([Location 2854](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2854))
- also automatically-derived traits, which means that a type in which all members are implementing Send automatically becomes a Send type. ([Location 2858](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2858))
- There are other arguments we can use in a route handling function, which we call request guards. They are called guards because if a request does not pass the validation inside the guard, the request will be rejected, and an error response will be returned. ([Location 2893](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2893))
- We will learn about and implement request guards throughout the book, but we will just use a request guard without implementing it in this chapter. FromRequest is already implemented for rocket::State<T>, so we can use it in the route handling function. ([Location 2905](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2905))
- Why do we add the 'a lifetime? We are adding a new reference argument, and Rust cannot infer which lifetime the returned &User should follow. In this case, we are saying the lifetime of the User reference should be as long as uuid. ([Location 2922](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2922))
- This example works fine with the Atomic type, but if you ever needed a more complex type to work with, such as String, Vec, or Struct, try using Mutex or RwLock from either the standard library or a third-party crate such as parking_lot. ([Location 2961](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=2961))
- serde is one of the most used and important libraries in Rust. The name comes from serialization and deserialization. ([Location 3094](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3094))
- We can either keep the user() function return as Option<User> and use user.ok(), or we change the return to Status::SomeStatus. Since we change the return type to either Ok(user) or Err(some_error), we can just return the Ok(user) variant, but we want to use map_err(|_| Status::NotFound) to change the error to a Status type. ([Location 3210](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3210))
- Other framework middleware may be able to inject any arbitrary data. In Rocket, the fairing can be used to modify the request but cannot be used to add information that is not part of the request. For example, we can use fairings to add a new HTTP header in the requests or responses. ([Location 3295](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3295))
- Some web frameworks might be able to terminate and directly respond to incoming requests, but in Rocket, the fairings cannot stop the incoming requests directly; the request must go through the route handling function, and then the route can create the proper response. ([Location 3297](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3297))
- Phase is a sealed trait, which means no other type outside the crate can implement this trait. We can define a sealed trait as follows: pub trait SomeTrait: private::Sealed {}. ([Location 3325](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3325))
- The Phase trait is sealed because Rocket authors intended only three phases in the Rocket application: rocket::Build, rocket::Ignite, and rocket::Orbit. ([Location 3328](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3328))
- And, rocket::fairing::Kind is defined as just an empty struct, pub struct Kind(_);, but Kind has the associated constants of Kind::Ignite, Kind::Liftoff, Kind::Request, Kind::Response, and Kind::Singleton. ([Location 3376](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3376))
- In Rust, we can declare associated items, which are items declared in traits or defined in implementations. ([Location 3383](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3383))
- We can use the Something::new() associated function to create a new instance of the type. There are also associated methods, just like associated functions but with self as the first parameter. ([Location 3396](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3396))
- Setting configuration using bitwise is a very common design pattern for packing multiple values into one variable. Some other languages even make this design pattern into its own type and call it bitset. ([Location 3442](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3442))
- Kind::Singleton is special. We can create multiple instances of fairings of the same type and attach them to Rocket. But, maybe we only want to allow one instance of the Fairing implementing type to be added. We can use Kind::Singleton and it will make sure only the last attached instance of this type will be added. ([Location 3465](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3465))
- Right now, our Rocket application manages VisitorCounter, but we did not add State<VisitorCounter> to the favicon() function. We might also want to add new route handling functions, but adding State<VisitorCounter> as an argument parameter for every route handling function is cumbersome. We can change VisitorCounter from a managed state into a fairing. ([Location 3472](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3472))
- Please note that we can use both State and Fairing in our application. Only use Fairing if we need to call this for every request. ([Location 3623](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3623))
- Rocket provided a sanctioned way to connect to some RDBMSs by using rocket_db_pools. That crate provides the database driver integration for Rocket. ([Location 3630](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3630))
- The database derives an automatically generated rocket_db_pools::Database implementation for the DBConnection type. Notice that we wrote the connection name "main_connection", just like what we have set in Rocket.toml. ([Location 3672](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3672))
- we will use the argon2id function, as it is more resistant to graphics processing unit (GPU) attacks and side-channel attacks. ([Location 3795](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3795))
- An implicit discriminator enum is an enum in which the member is not given a discriminator; it automatically starts from 0, for example, enum Status {Active, Inactive}. Using an implicit discriminator enum means we have to add a new data type in PostgreSQL using the CREATE TYPE SQL statement, for example, CREATE TYPE status AS ENUM ('active', 'inactive');. ([Location 3808](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3808))
- If we use an explicit discriminator enum, that is, an enum in which the member is given a discriminator, we can use the PostgreSQL INTEGER type and map it to rust i32. An explicit discriminator enum looks like the following: enum Status { Inactive = 0, Active = 1, } ([Location 3813](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3813))
- create, read, update, and delete (CRUD) functions. ([Location 3897](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3897))
- In a web application, an architecture style exists to perform operations based on the HTTP method. If we want to get an entity or a collection of entities, we use the HTTP GET method. If we want to create an entity, we use the HTTP POST method. If we want to update an entity, we use the HTTP PUT or PATCH method. And finally, if we want to delete an entity, we use the HTTP DELETE method. Using those HTTP methods to deliver data uniformly is called representational state transfer (REST), and an application following that constraint is called RESTful ([Location 3898](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3898))
- Before we create RESTful user routes for our application, let's think about what incoming parameters we want to handle and what responses we want to return. In the previous chapters, we have created routes that returned String, but most of the web is composed of HTML. ([Location 3906](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3906))
- The compiler will emit a warning if we define a variable or pass a parameter but do not use it, so we use an underscore (_) before the variable name in the function argument to suppress the compiler warning for now. ([Location 3926](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3926))
- Rocket handles catching the panic in the server using the std::panic::catch_unwind function. ([Location 3934](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3934))
- But, we have to create a new type, OurDateTime, because orphan rules mean we cannot implement rocket::form::FromForField for DateTime<Utc>;: ([Location 3950](https://readwise.io/to_kindle?action=open&asin=B09TB887G1&location=3950))