SlideShare a Scribd company logo
1 of 73
Download to read offline
NELL'IPERSPAZIO CON
ROCKET
IL FRAMEWORK WEB DI RUST
Commit University - Aprile 2024
1
WHO AM I
Denny Biasiolli
Full Stack Developer
(JavaScript, Python, Go, Rust)
Front End Developer UX/ UI
Fingerprint Compliance Services Ltd
Italy, Savigliano (CN)
@dennybiasiolli
denny.biasiolli@gmail.com
www.dennybiasiolli.com
2
2024, January
3
4
5
6
DISCLAIMER
I started the 2024 with the goal of learning Rust and
Rocket, and I'm sharing my journey with you.
7
DISCLAIMER
You are assumed to have a good grasp of the Rust
programming language.
https://doc.rust-lang.org/book/
8
WHAT IS ROCKET?
Rocket is a web framework for Rust
Fast
Easy
Flexible
Type-safe
9
ROCKET AIMS TO BE FUN
By ensuring that you write as little code
as possible to accomplish your task.
Allows you to focus on the fun parts of
writing web applications.
10
ROCKET CORE PHILOSOPHIES
Security, correctness, and developer experience
are paramount.
The path of least resistance should lead you to the most secure, correct web application,
though security and correctness should not come at the cost of a degraded developer
experience.
Rocket is easy to use while taking great measures to ensure that your application is secure
and correct without cognitive overhead.
11
ROCKET CORE PHILOSOPHIES
All request handling information
should be typed and self-contained.
Because the web and HTTP are themselves untyped (or stringly typed, as some call it), this
means that something or someone has to convert strings to native types.
Rocket does this for you with zero programming overhead.
What's more, Rocket's request handling is self-contained with zero global state: handlers
are regular functions with regular arguments.
12
ROCKET CORE PHILOSOPHIES
Decisions should not be forced.
Templates, serialization, sessions, and just about everything else are all pluggable, optional
components.
While Rocket has official support and libraries for each of these, they are completely
optional and swappable.
13
QUICKSTART - EXAMPLES
https://github.com/rwf2/Rocket
git clone https://github.com/rwf2/Rocket
cd Rocket
git checkout v0.5
cd examples/hello
cargo run
14
BASIC INSTALLATION
Cargo.toml
cargo add rocket
[dependencies]
rocket = "0.5.0"
15
INSTALLATION WITH FEATURES
Cargo.toml
cargo add rocket --features "json,secrets"
[dependencies]
rocket = { version = "0.5.0", features = ["json", "secrets"] }
16
HELLO, WORLD!
// src/main.rs
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/", routes![index])
}
17
HELLO, WORLD!
> cargo run
🔧 Configured for debug.
>> address: 127.0.0.1
>> port: 8000
>> workers: [..]
>> keep-alive: 5s
>> limits: [..]
>> tls: disabled
>> temp dir: /tmp
>> log level: normal
>> cli colors: true
🛰 Routes:
>> (index) GET /
🚀 Rocket has launched from http://127.0.0.1:8000
18
But wait, what's this?
Error: Rocket failed to bind network socket to
given address/port.
>> Address already in use (os error 48)
19
Rocket.toml FILE
## defaults for all profiles
[default]
port = 8000
## set only when compiled in debug mode,
## i.e, `cargo build` or `cargo run`
[debug]
port = 8001
https://rocket.rs/guide/v0.5/configuration/
20
Rocket.toml FILE
## set only when the `custom-profile` profile is selected,
## i.e, `ROCKET_PROFILE=custom-profile cargo build --release`
[custom-profile]
port = 9001
## set only when compiled in release mode,
## i.e, `cargo build --release`
[release]
port = 9999
https://rocket.rs/guide/v0.5/configuration/
21
ENVIRONMENT VARIABLES
Take precedence over Rocket.toml file.
Even at runtime.
ROCKET_PORT=8007 cargo run
https://rocket.rs/guide/v0.5/configuration/
22
ROCKET LIFECYCLE
1. Routing
2. Validation
3. Processing
4. Response
23
ROCKET LIFECYCLE
1. Routing
#[get("/bar")] // <-- route attribute
fn bar() -> &'static str {
"This is the /foo/bar route!"
}
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/foo", routes![bar]) // <-- route mounting
}
24
ROCKET LIFECYCLE
2. Validation
#[get("/hello/<name>/<age>")]
fn hello(name: &str, age: u8) -> String { // <-- validation
format!("Hello, {} year old named {}!", age, name)
}
25
ROCKET LIFECYCLE
3. Processing
#[get("/hello/<name>")]
fn hello(name: &str, age: u8) -> String {
/**
* Processing
* i.e, checking the age range, etc.
* This is the main business logic of an application.
* Processing completes by returning a Response.
*/
format!("Hello, {} year old named {}!", age, name)
}
26
ROCKET LIFECYCLE
4. Response
#[get("/")]
fn index() -> &'static str {
// return "Hello, world!"; // <-- response
"Hello, world!" // <-- response
}
27
LAUNCHING
Standard format
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/hello", routes![world])
}
28
LAUNCHING
allows you to start the server
is useful when a handle to the Future returned by launch() is desired
or when the return value of launch() is to be inspected.
#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
let _rocket = rocket::build()
.mount("/hello", routes![world])
.launch()
.await?;
Ok(())
}
29
DYNAMIC PATHS
#[get("/hello/<name>")]
fn hello(name: &str) -> String {
format!("Hello, {}!", name)
}
30
DYNAMIC PATHS
Any type, as long as the type implements the
FromParam trait.
#[get("/hello/<name>/<age>/<cool>")]
fn hello(name: &str, age: u8, cool: bool) -> String {
if cool {
format!("You're a cool {} year old, {}!", age, name)
} else {
format!(
"{}, we need to talk about your coolness.",
name
)
}
}
31
MULTIPLE SEGMENTS
use std::path::{Path, PathBuf};
use rocket::fs::NamedFile;
#[get("/<file..>")]
async fn files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("static/").join(file))
.await
.ok()
}
32
SERVE STATIC FILES
The easy way
use rocket::fs::FileServer;
// use rocket::fs::{relative, FileServer};
#[launch]
fn rocket() -> _ {
rocket::build()
// serve files from `/www/static` at path `/public`
.mount("/public", FileServer::from("/www/static"))
// or `relative!("static")` for a local directory
}
33
HTTP METHODS
get, post, put, delete, head, patch or options
#[get("/your/path")]
34
HTTP METHODS
What about HTML forms?
Form method="post"
Content-Type: application/x-www-form-urlencoded
First field name="_method"
First field value="<a valid HTTP method>"
<form action="/your/path" method="post">
<input type="hidden" name="_method" value="put" />
<!-- other fields -->
35
ASYNC ROUTES
use rocket::tokio::time::{sleep, Duration};
#[get("/delay/<seconds>")]
async fn delay(seconds: u64) -> String {
sleep(Duration::from_secs(seconds)).await;
format!("Waited for {} seconds", seconds)
}
36
TEMPLATES
https://rocket.rs/guide/v0.5/responses/#templates
cargo add rocket_dyn_templates --features "tera"
# or
cargo add rocket_dyn_templates --features "handlebars"
37
TEMPLATES
use rocket_dyn_templates::Template;
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/", routes![/* .. */])
.attach(Template::fairing()) // <- Add this line
}
38
TEMPLATES
use rocket_dyn_templates::Template;
#[get("/")]
fn index() -> Template {
// let context = /* object-like value */;
// Template::render("index", &context)
// or
Template::render("index", context! {
foo: 123,
})
}
39
TEMPLATES
Rocket discovers templates in the configurable
template_dir directory.
Templating support in Rocket is engine agnostic.
The engine used to render a template depends on the
template file's extension.
if a file ends with .hbs, Handlebars is used
if a file ends with .tera, Tera is used
40
TERA TEMPLATES
Note: The name of the template does not include its
extension.
For a template file named index.html.tera, call
render("index") and use the name "index" in
templates, i.e, extends "index" or extends
"base" for base.html.tera.
41
TERA TEMPLATES
Tera is a template engine inspired by Jinja2 and the Django template language.
https://keats.github.io/tera/
<title>{% block title %}{% endblock title %}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
42
REQUEST GUARDS
Types that implement the FromRequest trait
Used to extract data from the request
Can be used as arguments in request handlers
Protect a handler from being called erroneously
#[get("/<param>")]
fn index(param: isize, a: A, b: B, c: C) { /* ... */ }
// `A`, `B`, and `C` are request guards
https://api.rocket.rs/v0.5/rocket/request/trait.FromRequest
43
REQUEST GUARDS
FromRequest trait implementation
use rocket::request::{self, Request, FromRequest};
#[rocket::async_trait]
impl<'r> FromRequest<'r> for MyType {
type Error = MyError;
async fn from_request(req: &'r Request<'_>)
-> request::Outcome<Self, Self::Error> {
/* .. */
}
}
44
REQUEST GUARD EXAMPLES
struct ApiKey<'r>(&'r str);
#[derive(Debug)]
enum ApiKeyError {
Missing,
Invalid,
}
#[get("/sensitive")]
fn sensitive(key: ApiKey<'_>) -> &'static str {
"Sensitive data."
}
45
REQUEST GUARD EXAMPLES
#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
type Error = ApiKeyError;
async fn from_request(req: &'r Request<'_>)
-> Outcome<Self, Self::Error> {
/// Returns true if `key` is a valid API key string.
fn is_valid(key: &str) -> bool {
key == "valid_api_key"
}
match req.headers().get_one("x-api-key") {
None => Outcome::Error(
(Status::BadRequest, ApiKeyError::Missing)),
Some(key) if is_valid(key) => Outcome::Success(
ApiKey(key)),
Some(_) => Outcome::Error(
(Status::BadRequest, ApiKeyError::Invalid)),
}
}
}
46
REQUEST GUARD EXAMPLES
curl --location 'http://127.0.0.1:8000/api/sensitive'
# Output: 400 Bad Request
curl --location 'http://127.0.0.1:8000/api/sensitive' 
--header 'x-api-key: valid_api_key'
# Output: Sensitive data.
47
🍪COOKIES?
use rocket::form::Form;
use rocket::response::Redirect;
use rocket::http::CookieJar;
#[post("/", data = "<message>")]
fn submit(cookies: &CookieJar<'_>, message: Form<&str>) -> Red
cookies.add(("message", message.to_string()));
Redirect::to(uri!(index))
}
#[get("/")]
fn index(cookies: &CookieJar<'_>) -> Option<String> {
cookies.get("message")
.map(|crumb| format!("Message: {}", crumb.value()))
}
48
🍪PRIVATE COOKIES?
1. make sure the "secrets" feature is enabled
2. add "_private" to "add", "get" and "remove"
Encrypted using the 256-bit key specified in the
secret_key configuration parameter.
## in Cargo.toml
rocket = { version = "0.5.0", features = ["secrets
cookies.get_private
cookies.add_private
cookies.remove_private
49
FORM INPUT? YES, PLEASE!
Rocket supports both
"multipart" and "x-www-form-urlencoded" forms
out of the box,
enabled by the Form data guard
and derivable FromForm trait.
https://rocket.rs/guide/v0.5/requests/#forms
50
FORM INPUT
use rocket::form::Form;
#[derive(FromForm)]
struct Task<'r> {
description: &'r str,
complete: bool
}
#[post("/todo", data = "<task>")]
fn new(task: Form<Task<'_>>) { /* .. */ }
51
FORM INPUT
curl --location 'http://127.0.0.1:8001/todo' 
--form 'description="test"' 
--form 'complete="true"'
curl --location 'http://127.0.0.1:8001/todo' 
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'description=test' 
--data-urlencode 'complete=true'
# or
# Output form errors with:
# 422 Unprocessable Entity
# or
# 415 Unsupported Media Type
52
QUERY PARAMS? YES, PLEASE!
Query strings are URL-encoded forms
that appear in the URL of a request.
Query parameters are declared like path parameters
but otherwise handled like regular URL-encoded form
fields.
https://rocket.rs/guide/v0.5/requests/#query-strings
53
QUERY PARAMS
or
#[get("/tasks?<filter>")]
fn tasks(filter: &str) { /* .. */ }
use rocket::form::Form;
#[derive(FromForm)]
struct Task<'r> {
description: &'r str,
complete: bool
}
#[get("/tasks?<task>")]
fn tasks(task: Task<'_>) { /* .. */ }
// or
#[get("/tasks?<task..>")]
fn tasks(task: Task<'_>) { /* .. */ }
54
QUERY PARAMS
curl --location 
'http://url/tasks?filter=foo'
# or
curl --location 
'http://url/tasks?task.description=bar&task.complete=true'
curl --location 
'http://url/tasks?description=baz&complete=true'
55
JSON INPUT? YES, PLEASE!
Make sure the "json" feature is enabled
The Json<T> guard deserializes body data as JSON.
The only condition is that the generic type T
implements the Deserialize trait from serde.
## in Cargo.toml
rocket = { version = "0.5.0", features = ["json"] }
https://rocket.rs/guide/v0.5/requests/#json
56
JSON INPUT
use rocket::serde::{Deserialize, json::Json};
#[derive(Deserialize)]
#[serde(crate = "rocket::serde")]
struct Task<'r> {
description: &'r str,
complete: bool
}
#[post("/todo", data = "<task>")]
fn new(task: Json<Task<'_>>) { /* .. */ }
57
JSON INPUT
curl --location 'http://127.0.0.1:8001/todo' 
--header 'Content-Type: application/json' 
--data '{
"description": "My Description",
"complete": false
}'
# or
# Output JSON errors with:
# 422 Unprocessable Entity
58
JSON OUTPUT
use rocket::serde::{Deserialize, Serialize, json::Json};
#[derive(Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
struct Task<'r> {
description: &'r str,
complete: bool
}
#[post("/todo", data = "<task>")]
fn new(task: Json<Task<'_>>) -> Json<Task<'_>> {
task
}
59
JSON OUTPUT
curl --location 'http://127.0.0.1:8001/todo' 
--header 'Content-Type: application/json' 
--data '{
"description": "My Description",
"complete": false
}'
# Output:
# {"description":"My Description","complete":false}
60
ERROR CATCHERS
https://rocket.rs/guide/v0.5/requests/#error-catchers
use rocket::Request;
#[catch(404)]
fn not_found() { /* .. */ }
// or
#[catch(404)]
fn not_found(req: &Request) {
format!("Sorry, '{}' is not a valid path.", req.uri())
}
61
ERROR CATCHERS
fn main() {
rocket::build()
.register("/", catchers![not_found]);
.register("/foo", catchers![foo_not_found]);
}
62
MANAGED (GLOBAL) STATE
The state is managed on a per-type basis
1. Call manage on the Rocket instance corresponding
to your application with the initial value of the state.
use std::sync::atomic::AtomicUsize;
struct HitCount {
count: AtomicUsize
}
rocket::build()
.manage(HitCount { count: AtomicUsize::new(0) });
63
MANAGED (GLOBAL) STATE
2. Add a &State<T> type to any request handler,
where T is the type of the value passed into manage.
use rocket::State;
#[get("/count")]
fn count(hit_count: &State<HitCount>) -> String {
let current_count = hit_count.count.load(Ordering::Rela
format!("Number of visits: {}", current_count)
}
64
REQUEST-LOCAL STATE
use rocket::request::{self, Request, FromRequest};
/// A global atomic counter for generating IDs.
static ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
/// A type that represents a request's ID.
struct RequestId(pub usize);
#[get("/")]
fn id(id: &RequestId) -> String {
format!("This is request #{}.", id.0)
}
65
REQUEST-LOCAL STATE
/// Returns the current request's ID,
/// assigning one only as necessary.
#[rocket::async_trait]
impl<'r> FromRequest<'r> for &'r RequestId {
type Error = ();
async fn from_request(request: &'r Request<'_>)
-> request::Outcome<Self, Self::Error> {
// The closure passed to `local_cache`
// will be executed at most once per request:
// When requested again, will return the same value.
request::Outcome::Success(request.local_cache(|| {
RequestId(ID_COUNTER.fetch_add(1, Ordering::Relaxe
}))
}
66
DATABASES
Rocket includes built-in, ORM-agnostic support for
databases via rocket_db_pools.
The library simplifies accessing one or more databases
via connection pools: data structures that maintain
active database connections for use in the application.
cargo add rocket_db_pools --features "sqlx_sqlite"
# or
cargo add rocket_db_pools --features "sqlx_postgres"
# or
cargo add rocket_db_pools --features "diesel_postgres"
https://api.rocket.rs/v0.5/rocket_db_pools/#supported-drivers
67
DATABASES
Configure at least a URL for the database under
databases.$name (in Rocket.toml), where $name is
your choice of database name:
[default.databases.custom_name]
url = "database.sqlite"
[default.databases.custom_name_postgres]
url = "postgresql://[user[:password]@][host][:port][/dbname]"
68
DATABASES
#[macro_use] extern crate rocket;
use rocket_db_pools::{Database, Connection};
use rocket_db_pools::sqlx::{self, Row};
#[derive(Database)]
#[database("custom_name")]
struct Logs(sqlx::SqlitePool); // or sqlx::PgPool
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(Logs::init())
.mount("/", routes![read])
}
69
DATABASES
#[get("/<id>")]
async fn read(mut db: Connection<Logs>, id: i64)
-> Option<String> {
sqlx::query("SELECT content FROM logs WHERE id = ?")
.bind(id)
.fetch_one(&mut **db).await
.and_then(|r| Ok(r.try_get(0)?))
.ok()
}
70
DATABASES
use rocket::serde::{Serialize, Deserialize, json::Json};
use rocket_db_pools::{Database, Connection};
use rocket_db_pools::diesel::{PgPool, prelude::*};
#[derive(Database)]
#[database("custom_name_postgres")]
struct Db(PgPool);
#[derive(Debug, Clone, Deserialize, Serialize, Queryable, Inse
#[serde(crate = "rocket::serde")]
#[diesel(table_name = posts)]
struct Post {
#[serde(skip_deserializing)]
id: Option<i64>,
title: String,
text: String,
#[serde(skip_deserializing)]
published: bool,
}
71
DATABASES
table! {
posts (id) {
id -> Nullable<BigInt>,
title -> Text,
text -> Text,
published -> Bool,
}
}
#[get("/<id>")]
async fn read(mut db: Connection<Db>, id: i64) -> Option<Json<
posts::table
.filter(posts::id.eq(id))
.first(&mut db)
.await
.map(Json)
.ok()
}
72
MUCH, MUCH MORE!
@dennybiasiolli
rocket.rs/guide/v0.5/
doc.rust-lang.org/book/
github.com/rwf2/Rocket
www.dennybiasiolli.com
73

More Related Content

Similar to Nell’iperspazio con Rocket: il Framework Web di Rust!

Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyLaunchAny
 
How Stuffle uses Docker for deployments
How Stuffle uses Docker for deploymentsHow Stuffle uses Docker for deployments
How Stuffle uses Docker for deploymentsRobinBrandt
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareAlona Mekhovova
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersAlessandro Sanino
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Metosin Oy
 
Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)dantleech
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725miguel dominguez
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725MortazaJohari
 
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Yevgeniy Brikman
 
June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules Puppet
 
Portland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modulesPortland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modulesPuppet
 
[Codelab 2017] Docker 기초 및 활용 방안
[Codelab 2017] Docker 기초 및 활용 방안[Codelab 2017] Docker 기초 및 활용 방안
[Codelab 2017] Docker 기초 및 활용 방안양재동 코드랩
 
Java - A broad introduction
Java - A broad introductionJava - A broad introduction
Java - A broad introductionBirol Efe
 
Code Documentation. That ugly thing...
Code Documentation. That ugly thing...Code Documentation. That ugly thing...
Code Documentation. That ugly thing...Christos Manios
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Guillaume Laforge
 

Similar to Nell’iperspazio con Rocket: il Framework Web di Rust! (20)

Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
How Stuffle uses Docker for deployments
How Stuffle uses Docker for deploymentsHow Stuffle uses Docker for deployments
How Stuffle uses Docker for deployments
 
NodeJS
NodeJSNodeJS
NodeJS
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to Gophers
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
 
Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725Infrastructureascode slideshare-160331143725
Infrastructureascode slideshare-160331143725
 
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
 
June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules
 
Portland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modulesPortland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modules
 
[Codelab 2017] Docker 기초 및 활용 방안
[Codelab 2017] Docker 기초 및 활용 방안[Codelab 2017] Docker 기초 및 활용 방안
[Codelab 2017] Docker 기초 및 활용 방안
 
Java - A broad introduction
Java - A broad introductionJava - A broad introduction
Java - A broad introduction
 
Android networking-2
Android networking-2Android networking-2
Android networking-2
 
Code Documentation. That ugly thing...
Code Documentation. That ugly thing...Code Documentation. That ugly thing...
Code Documentation. That ugly thing...
 
Book
BookBook
Book
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Demystifying Maven
Demystifying MavenDemystifying Maven
Demystifying Maven
 
Dart Workshop
Dart WorkshopDart Workshop
Dart Workshop
 

More from Commit University

Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfCommit University
 
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfAccelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfCommit University
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Commit University
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit University
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PACommit University
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Commit University
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting forCommit University
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityCommit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfCommit University
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Commit University
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsCommit University
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftCommit University
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneCommit University
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcCommit University
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeCommit University
 
Alpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkAlpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkCommit University
 

More from Commit University (20)

Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
 
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfAccelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
 
Slide-10years.pdf
Slide-10years.pdfSlide-10years.pdf
Slide-10years.pdf
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
 
Vue.js slots.pdf
Vue.js slots.pdfVue.js slots.pdf
Vue.js slots.pdf
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptx
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PA
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting for
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdf
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step Functions
 
KMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and SwiftKMM survival guide: how to tackle struggles between Kotlin and Swift
KMM survival guide: how to tackle struggles between Kotlin and Swift
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lc
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-Code
 
SwiftUI vs UIKit
SwiftUI vs UIKitSwiftUI vs UIKit
SwiftUI vs UIKit
 
Alpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkAlpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript framework
 

Recently uploaded

Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Hiroshi SHIBATA
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctBrainSell Technologies
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe中 央社
 
Using IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandUsing IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandIES VE
 
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...ScyllaDB
 
Intro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxIntro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxFIDO Alliance
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxFIDO Alliance
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingScyllaDB
 
How we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfHow we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfSrushith Repakula
 
State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!Memoori
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxFIDO Alliance
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightSafe Software
 
Where to Learn More About FDO _ Richard at FIDO Alliance.pdf
Where to Learn More About FDO _ Richard at FIDO Alliance.pdfWhere to Learn More About FDO _ Richard at FIDO Alliance.pdf
Where to Learn More About FDO _ Richard at FIDO Alliance.pdfFIDO Alliance
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdfMuhammad Subhan
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?Mark Billinghurst
 
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdfSimplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdfFIDO Alliance
 
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Paige Cruz
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsLeah Henrickson
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentationyogeshlabana357357
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024Lorenzo Miniero
 

Recently uploaded (20)

Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage Intacct
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe
 
Using IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandUsing IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & Ireland
 
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
 
Intro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxIntro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptx
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream Processing
 
How we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdfHow we scaled to 80K users by doing nothing!.pdf
How we scaled to 80K users by doing nothing!.pdf
 
State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
Where to Learn More About FDO _ Richard at FIDO Alliance.pdf
Where to Learn More About FDO _ Richard at FIDO Alliance.pdfWhere to Learn More About FDO _ Richard at FIDO Alliance.pdf
Where to Learn More About FDO _ Richard at FIDO Alliance.pdf
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdfSimplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
 
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentation
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 

Nell’iperspazio con Rocket: il Framework Web di Rust!

  • 1. NELL'IPERSPAZIO CON ROCKET IL FRAMEWORK WEB DI RUST Commit University - Aprile 2024 1
  • 2. WHO AM I Denny Biasiolli Full Stack Developer (JavaScript, Python, Go, Rust) Front End Developer UX/ UI Fingerprint Compliance Services Ltd Italy, Savigliano (CN) @dennybiasiolli denny.biasiolli@gmail.com www.dennybiasiolli.com 2
  • 4. 4
  • 5. 5
  • 6. 6
  • 7. DISCLAIMER I started the 2024 with the goal of learning Rust and Rocket, and I'm sharing my journey with you. 7
  • 8. DISCLAIMER You are assumed to have a good grasp of the Rust programming language. https://doc.rust-lang.org/book/ 8
  • 9. WHAT IS ROCKET? Rocket is a web framework for Rust Fast Easy Flexible Type-safe 9
  • 10. ROCKET AIMS TO BE FUN By ensuring that you write as little code as possible to accomplish your task. Allows you to focus on the fun parts of writing web applications. 10
  • 11. ROCKET CORE PHILOSOPHIES Security, correctness, and developer experience are paramount. The path of least resistance should lead you to the most secure, correct web application, though security and correctness should not come at the cost of a degraded developer experience. Rocket is easy to use while taking great measures to ensure that your application is secure and correct without cognitive overhead. 11
  • 12. ROCKET CORE PHILOSOPHIES All request handling information should be typed and self-contained. Because the web and HTTP are themselves untyped (or stringly typed, as some call it), this means that something or someone has to convert strings to native types. Rocket does this for you with zero programming overhead. What's more, Rocket's request handling is self-contained with zero global state: handlers are regular functions with regular arguments. 12
  • 13. ROCKET CORE PHILOSOPHIES Decisions should not be forced. Templates, serialization, sessions, and just about everything else are all pluggable, optional components. While Rocket has official support and libraries for each of these, they are completely optional and swappable. 13
  • 14. QUICKSTART - EXAMPLES https://github.com/rwf2/Rocket git clone https://github.com/rwf2/Rocket cd Rocket git checkout v0.5 cd examples/hello cargo run 14
  • 15. BASIC INSTALLATION Cargo.toml cargo add rocket [dependencies] rocket = "0.5.0" 15
  • 16. INSTALLATION WITH FEATURES Cargo.toml cargo add rocket --features "json,secrets" [dependencies] rocket = { version = "0.5.0", features = ["json", "secrets"] } 16
  • 17. HELLO, WORLD! // src/main.rs #[macro_use] extern crate rocket; #[get("/")] fn index() -> &'static str { "Hello, world!" } #[launch] fn rocket() -> _ { rocket::build() .mount("/", routes![index]) } 17
  • 18. HELLO, WORLD! > cargo run 🔧 Configured for debug. >> address: 127.0.0.1 >> port: 8000 >> workers: [..] >> keep-alive: 5s >> limits: [..] >> tls: disabled >> temp dir: /tmp >> log level: normal >> cli colors: true 🛰 Routes: >> (index) GET / 🚀 Rocket has launched from http://127.0.0.1:8000 18
  • 19. But wait, what's this? Error: Rocket failed to bind network socket to given address/port. >> Address already in use (os error 48) 19
  • 20. Rocket.toml FILE ## defaults for all profiles [default] port = 8000 ## set only when compiled in debug mode, ## i.e, `cargo build` or `cargo run` [debug] port = 8001 https://rocket.rs/guide/v0.5/configuration/ 20
  • 21. Rocket.toml FILE ## set only when the `custom-profile` profile is selected, ## i.e, `ROCKET_PROFILE=custom-profile cargo build --release` [custom-profile] port = 9001 ## set only when compiled in release mode, ## i.e, `cargo build --release` [release] port = 9999 https://rocket.rs/guide/v0.5/configuration/ 21
  • 22. ENVIRONMENT VARIABLES Take precedence over Rocket.toml file. Even at runtime. ROCKET_PORT=8007 cargo run https://rocket.rs/guide/v0.5/configuration/ 22
  • 23. ROCKET LIFECYCLE 1. Routing 2. Validation 3. Processing 4. Response 23
  • 24. ROCKET LIFECYCLE 1. Routing #[get("/bar")] // <-- route attribute fn bar() -> &'static str { "This is the /foo/bar route!" } #[launch] fn rocket() -> _ { rocket::build() .mount("/foo", routes![bar]) // <-- route mounting } 24
  • 25. ROCKET LIFECYCLE 2. Validation #[get("/hello/<name>/<age>")] fn hello(name: &str, age: u8) -> String { // <-- validation format!("Hello, {} year old named {}!", age, name) } 25
  • 26. ROCKET LIFECYCLE 3. Processing #[get("/hello/<name>")] fn hello(name: &str, age: u8) -> String { /** * Processing * i.e, checking the age range, etc. * This is the main business logic of an application. * Processing completes by returning a Response. */ format!("Hello, {} year old named {}!", age, name) } 26
  • 27. ROCKET LIFECYCLE 4. Response #[get("/")] fn index() -> &'static str { // return "Hello, world!"; // <-- response "Hello, world!" // <-- response } 27
  • 28. LAUNCHING Standard format #[launch] fn rocket() -> _ { rocket::build() .mount("/hello", routes![world]) } 28
  • 29. LAUNCHING allows you to start the server is useful when a handle to the Future returned by launch() is desired or when the return value of launch() is to be inspected. #[rocket::main] async fn main() -> Result<(), rocket::Error> { let _rocket = rocket::build() .mount("/hello", routes![world]) .launch() .await?; Ok(()) } 29
  • 30. DYNAMIC PATHS #[get("/hello/<name>")] fn hello(name: &str) -> String { format!("Hello, {}!", name) } 30
  • 31. DYNAMIC PATHS Any type, as long as the type implements the FromParam trait. #[get("/hello/<name>/<age>/<cool>")] fn hello(name: &str, age: u8, cool: bool) -> String { if cool { format!("You're a cool {} year old, {}!", age, name) } else { format!( "{}, we need to talk about your coolness.", name ) } } 31
  • 32. MULTIPLE SEGMENTS use std::path::{Path, PathBuf}; use rocket::fs::NamedFile; #[get("/<file..>")] async fn files(file: PathBuf) -> Option<NamedFile> { NamedFile::open(Path::new("static/").join(file)) .await .ok() } 32
  • 33. SERVE STATIC FILES The easy way use rocket::fs::FileServer; // use rocket::fs::{relative, FileServer}; #[launch] fn rocket() -> _ { rocket::build() // serve files from `/www/static` at path `/public` .mount("/public", FileServer::from("/www/static")) // or `relative!("static")` for a local directory } 33
  • 34. HTTP METHODS get, post, put, delete, head, patch or options #[get("/your/path")] 34
  • 35. HTTP METHODS What about HTML forms? Form method="post" Content-Type: application/x-www-form-urlencoded First field name="_method" First field value="<a valid HTTP method>" <form action="/your/path" method="post"> <input type="hidden" name="_method" value="put" /> <!-- other fields --> 35
  • 36. ASYNC ROUTES use rocket::tokio::time::{sleep, Duration}; #[get("/delay/<seconds>")] async fn delay(seconds: u64) -> String { sleep(Duration::from_secs(seconds)).await; format!("Waited for {} seconds", seconds) } 36
  • 37. TEMPLATES https://rocket.rs/guide/v0.5/responses/#templates cargo add rocket_dyn_templates --features "tera" # or cargo add rocket_dyn_templates --features "handlebars" 37
  • 38. TEMPLATES use rocket_dyn_templates::Template; #[launch] fn rocket() -> _ { rocket::build() .mount("/", routes![/* .. */]) .attach(Template::fairing()) // <- Add this line } 38
  • 39. TEMPLATES use rocket_dyn_templates::Template; #[get("/")] fn index() -> Template { // let context = /* object-like value */; // Template::render("index", &context) // or Template::render("index", context! { foo: 123, }) } 39
  • 40. TEMPLATES Rocket discovers templates in the configurable template_dir directory. Templating support in Rocket is engine agnostic. The engine used to render a template depends on the template file's extension. if a file ends with .hbs, Handlebars is used if a file ends with .tera, Tera is used 40
  • 41. TERA TEMPLATES Note: The name of the template does not include its extension. For a template file named index.html.tera, call render("index") and use the name "index" in templates, i.e, extends "index" or extends "base" for base.html.tera. 41
  • 42. TERA TEMPLATES Tera is a template engine inspired by Jinja2 and the Django template language. https://keats.github.io/tera/ <title>{% block title %}{% endblock title %}</title> <ul> {% for user in users %} <li><a href="{{ user.url }}">{{ user.username }}</a></li> {% endfor %} </ul> 42
  • 43. REQUEST GUARDS Types that implement the FromRequest trait Used to extract data from the request Can be used as arguments in request handlers Protect a handler from being called erroneously #[get("/<param>")] fn index(param: isize, a: A, b: B, c: C) { /* ... */ } // `A`, `B`, and `C` are request guards https://api.rocket.rs/v0.5/rocket/request/trait.FromRequest 43
  • 44. REQUEST GUARDS FromRequest trait implementation use rocket::request::{self, Request, FromRequest}; #[rocket::async_trait] impl<'r> FromRequest<'r> for MyType { type Error = MyError; async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> { /* .. */ } } 44
  • 45. REQUEST GUARD EXAMPLES struct ApiKey<'r>(&'r str); #[derive(Debug)] enum ApiKeyError { Missing, Invalid, } #[get("/sensitive")] fn sensitive(key: ApiKey<'_>) -> &'static str { "Sensitive data." } 45
  • 46. REQUEST GUARD EXAMPLES #[rocket::async_trait] impl<'r> FromRequest<'r> for ApiKey<'r> { type Error = ApiKeyError; async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> { /// Returns true if `key` is a valid API key string. fn is_valid(key: &str) -> bool { key == "valid_api_key" } match req.headers().get_one("x-api-key") { None => Outcome::Error( (Status::BadRequest, ApiKeyError::Missing)), Some(key) if is_valid(key) => Outcome::Success( ApiKey(key)), Some(_) => Outcome::Error( (Status::BadRequest, ApiKeyError::Invalid)), } } } 46
  • 47. REQUEST GUARD EXAMPLES curl --location 'http://127.0.0.1:8000/api/sensitive' # Output: 400 Bad Request curl --location 'http://127.0.0.1:8000/api/sensitive' --header 'x-api-key: valid_api_key' # Output: Sensitive data. 47
  • 48. 🍪COOKIES? use rocket::form::Form; use rocket::response::Redirect; use rocket::http::CookieJar; #[post("/", data = "<message>")] fn submit(cookies: &CookieJar<'_>, message: Form<&str>) -> Red cookies.add(("message", message.to_string())); Redirect::to(uri!(index)) } #[get("/")] fn index(cookies: &CookieJar<'_>) -> Option<String> { cookies.get("message") .map(|crumb| format!("Message: {}", crumb.value())) } 48
  • 49. 🍪PRIVATE COOKIES? 1. make sure the "secrets" feature is enabled 2. add "_private" to "add", "get" and "remove" Encrypted using the 256-bit key specified in the secret_key configuration parameter. ## in Cargo.toml rocket = { version = "0.5.0", features = ["secrets cookies.get_private cookies.add_private cookies.remove_private 49
  • 50. FORM INPUT? YES, PLEASE! Rocket supports both "multipart" and "x-www-form-urlencoded" forms out of the box, enabled by the Form data guard and derivable FromForm trait. https://rocket.rs/guide/v0.5/requests/#forms 50
  • 51. FORM INPUT use rocket::form::Form; #[derive(FromForm)] struct Task<'r> { description: &'r str, complete: bool } #[post("/todo", data = "<task>")] fn new(task: Form<Task<'_>>) { /* .. */ } 51
  • 52. FORM INPUT curl --location 'http://127.0.0.1:8001/todo' --form 'description="test"' --form 'complete="true"' curl --location 'http://127.0.0.1:8001/todo' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'description=test' --data-urlencode 'complete=true' # or # Output form errors with: # 422 Unprocessable Entity # or # 415 Unsupported Media Type 52
  • 53. QUERY PARAMS? YES, PLEASE! Query strings are URL-encoded forms that appear in the URL of a request. Query parameters are declared like path parameters but otherwise handled like regular URL-encoded form fields. https://rocket.rs/guide/v0.5/requests/#query-strings 53
  • 54. QUERY PARAMS or #[get("/tasks?<filter>")] fn tasks(filter: &str) { /* .. */ } use rocket::form::Form; #[derive(FromForm)] struct Task<'r> { description: &'r str, complete: bool } #[get("/tasks?<task>")] fn tasks(task: Task<'_>) { /* .. */ } // or #[get("/tasks?<task..>")] fn tasks(task: Task<'_>) { /* .. */ } 54
  • 55. QUERY PARAMS curl --location 'http://url/tasks?filter=foo' # or curl --location 'http://url/tasks?task.description=bar&task.complete=true' curl --location 'http://url/tasks?description=baz&complete=true' 55
  • 56. JSON INPUT? YES, PLEASE! Make sure the "json" feature is enabled The Json<T> guard deserializes body data as JSON. The only condition is that the generic type T implements the Deserialize trait from serde. ## in Cargo.toml rocket = { version = "0.5.0", features = ["json"] } https://rocket.rs/guide/v0.5/requests/#json 56
  • 57. JSON INPUT use rocket::serde::{Deserialize, json::Json}; #[derive(Deserialize)] #[serde(crate = "rocket::serde")] struct Task<'r> { description: &'r str, complete: bool } #[post("/todo", data = "<task>")] fn new(task: Json<Task<'_>>) { /* .. */ } 57
  • 58. JSON INPUT curl --location 'http://127.0.0.1:8001/todo' --header 'Content-Type: application/json' --data '{ "description": "My Description", "complete": false }' # or # Output JSON errors with: # 422 Unprocessable Entity 58
  • 59. JSON OUTPUT use rocket::serde::{Deserialize, Serialize, json::Json}; #[derive(Deserialize, Serialize)] #[serde(crate = "rocket::serde")] struct Task<'r> { description: &'r str, complete: bool } #[post("/todo", data = "<task>")] fn new(task: Json<Task<'_>>) -> Json<Task<'_>> { task } 59
  • 60. JSON OUTPUT curl --location 'http://127.0.0.1:8001/todo' --header 'Content-Type: application/json' --data '{ "description": "My Description", "complete": false }' # Output: # {"description":"My Description","complete":false} 60
  • 61. ERROR CATCHERS https://rocket.rs/guide/v0.5/requests/#error-catchers use rocket::Request; #[catch(404)] fn not_found() { /* .. */ } // or #[catch(404)] fn not_found(req: &Request) { format!("Sorry, '{}' is not a valid path.", req.uri()) } 61
  • 62. ERROR CATCHERS fn main() { rocket::build() .register("/", catchers![not_found]); .register("/foo", catchers![foo_not_found]); } 62
  • 63. MANAGED (GLOBAL) STATE The state is managed on a per-type basis 1. Call manage on the Rocket instance corresponding to your application with the initial value of the state. use std::sync::atomic::AtomicUsize; struct HitCount { count: AtomicUsize } rocket::build() .manage(HitCount { count: AtomicUsize::new(0) }); 63
  • 64. MANAGED (GLOBAL) STATE 2. Add a &State<T> type to any request handler, where T is the type of the value passed into manage. use rocket::State; #[get("/count")] fn count(hit_count: &State<HitCount>) -> String { let current_count = hit_count.count.load(Ordering::Rela format!("Number of visits: {}", current_count) } 64
  • 65. REQUEST-LOCAL STATE use rocket::request::{self, Request, FromRequest}; /// A global atomic counter for generating IDs. static ID_COUNTER: AtomicUsize = AtomicUsize::new(0); /// A type that represents a request's ID. struct RequestId(pub usize); #[get("/")] fn id(id: &RequestId) -> String { format!("This is request #{}.", id.0) } 65
  • 66. REQUEST-LOCAL STATE /// Returns the current request's ID, /// assigning one only as necessary. #[rocket::async_trait] impl<'r> FromRequest<'r> for &'r RequestId { type Error = (); async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> { // The closure passed to `local_cache` // will be executed at most once per request: // When requested again, will return the same value. request::Outcome::Success(request.local_cache(|| { RequestId(ID_COUNTER.fetch_add(1, Ordering::Relaxe })) } 66
  • 67. DATABASES Rocket includes built-in, ORM-agnostic support for databases via rocket_db_pools. The library simplifies accessing one or more databases via connection pools: data structures that maintain active database connections for use in the application. cargo add rocket_db_pools --features "sqlx_sqlite" # or cargo add rocket_db_pools --features "sqlx_postgres" # or cargo add rocket_db_pools --features "diesel_postgres" https://api.rocket.rs/v0.5/rocket_db_pools/#supported-drivers 67
  • 68. DATABASES Configure at least a URL for the database under databases.$name (in Rocket.toml), where $name is your choice of database name: [default.databases.custom_name] url = "database.sqlite" [default.databases.custom_name_postgres] url = "postgresql://[user[:password]@][host][:port][/dbname]" 68
  • 69. DATABASES #[macro_use] extern crate rocket; use rocket_db_pools::{Database, Connection}; use rocket_db_pools::sqlx::{self, Row}; #[derive(Database)] #[database("custom_name")] struct Logs(sqlx::SqlitePool); // or sqlx::PgPool #[launch] fn rocket() -> _ { rocket::build() .attach(Logs::init()) .mount("/", routes![read]) } 69
  • 70. DATABASES #[get("/<id>")] async fn read(mut db: Connection<Logs>, id: i64) -> Option<String> { sqlx::query("SELECT content FROM logs WHERE id = ?") .bind(id) .fetch_one(&mut **db).await .and_then(|r| Ok(r.try_get(0)?)) .ok() } 70
  • 71. DATABASES use rocket::serde::{Serialize, Deserialize, json::Json}; use rocket_db_pools::{Database, Connection}; use rocket_db_pools::diesel::{PgPool, prelude::*}; #[derive(Database)] #[database("custom_name_postgres")] struct Db(PgPool); #[derive(Debug, Clone, Deserialize, Serialize, Queryable, Inse #[serde(crate = "rocket::serde")] #[diesel(table_name = posts)] struct Post { #[serde(skip_deserializing)] id: Option<i64>, title: String, text: String, #[serde(skip_deserializing)] published: bool, } 71
  • 72. DATABASES table! { posts (id) { id -> Nullable<BigInt>, title -> Text, text -> Text, published -> Bool, } } #[get("/<id>")] async fn read(mut db: Connection<Db>, id: i64) -> Option<Json< posts::table .filter(posts::id.eq(id)) .first(&mut db) .await .map(Json) .ok() } 72