Actix-Web
actix-web is a framework for writting web applications and REST APIs.
Installation
# To install:
cargo add actix-web
# Recommended for validation
cargo add validator actix-web-validator
Simple example
#[get("/hello")
async fn hello() -> Response {
HttpResponse::Ok().body("Hello!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(move || {
App::new()
.app_data(here_you_can_add_dependencies)
.service(hello)
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
JSON request bodies
To parse a JSON body from a request, you define a struct, which represents the body, and then use the web::Json extractor.
#[derive(Deserialize)]
struct HelloRequest {
name: String,
}
#[post("/hello")
async fn hello(payload: web::Json<HelloRequest>) -> Response {
let name = payload.name;
HttpResponse::Ok().body(format!("Hello, {name}!"))
}
You can also use the actix-web-validator package to create a validation. The request must then match your rules:
#[derive(Deserialize, Validate)]
struct HelloRequest {
#[validate(length(min = 1, max = 32)]
name: String,
}
#[post("/hello")
async fn hello(payload: actix_web_validator::Json<HelloRequest>) -> Response {
let name = payload.name;
HttpResponse::Ok().body(format!("Hello, {name}!"))
}
Scopes
You can group multiple services into a scope, to give them the same prefix.
let v1 = web::scope("/api/v1")
.service(list_entities)
.service(create_entity)
.service(delete_entity);
App::new()
.service(v1)
Custom extractors
Extractors are used in the parameter lists of your service functions. You can write own to extract information from a request (e.g. get a user by authorization header). To write such a custom header, you need to create a struct (which will be used in the parameter list and contain the extracted information) and then implmenet the FromRequest trait:
struct MyExtractor {
...
}
impl FromRequest for MyExtractor {
type Error = actix_web::Error;
type Future = future_utils::LocalBoxFuture<'static, Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
let req = req.clone();
Box::pin(async move {
// Do extraction...
Ok(MyExtractor { ... })
})
}
}