Sådan kloner du titler i JavaScript
Rust + Actix-web: Byg APIs der faktisk kan holde til noget
Lad os være ærlige—de fleste af os ryger direkte efter Node.js eller Python, når vi skal have bygget en hurtig REST API. Vi kender afvejningerne: hastighed i udvikling versus ydeevne, hurtig prototyping versus produktionsklar pålidelighed. Men hvad nu hvis du kunne få begge dele?
Det er løftet fra Rust, og Actix-web er det framework der gør det tilgængeligt for os webudviklere.
Hvorfor Rust til APIs? (Den ubekvemme sandhed)
Før vi skriver én linje kode, lad os tage fat i elefanten i rummet: Rust har en stejl læringskurve. Den er ikke nådig. Borrow checkeren vil ydmyge dig. Du kommer til at bruge timer på at debugge lifetimes i stedet for at levere features.
Men her er det, der gik op for mig: Rust giver dig ikke et valg mellem sikkerhed og hastighed. Din API vil være hukommelsessikker som standard—ingen null pointer exceptions, ingen data races, ingen garbage collection pauses der dræber dine p99 latencies. Når du betjener tusindvis af requests i sekundet, betyder den konsistens noget.
For startups og udviklere der skalerer systemer, betyder det forudsigelig ydeevne uden det operationelle overhead det indebærer at administrere et separat sikkerhedslag.
Kom i gang med Actix-web
Actix-web er inspireret af (men ikke tilknyttet) Elixir/Phoenix frameworket. Det omfavner actor-modellen og leverer en ergonomisk API, der føles genkendelig, hvis du har brugt Express, Fastify eller lignende frameworks.
Opsæt dit projekt
cargo new rust-api-demo
cd rust-api-demo
cargo add actix-web actix-rt
Din første endpoint
use actix_web::{web, App, HttpServer, HttpResponse};
async fn health_check() -> HttpResponse {
HttpResponse::Ok().json(serde_json::json!({
"status": "healthy",
"version": env!("CARGO_PKG_VERSION")
}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/health", web::get().to(health_check))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Den health endpoint? Den kompilerer på millisekunder og starter på mikrosekunder. Kør cargo run og ram localhost:8080/health—du får din JSON response øjeblikkeligt.
Byg en rigtig API: Todos med CRUD operationer
Lad os bygge noget mere praktisk—en Todo API med fuld CRUD.
Definer din datamodel
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
use std::cell::Cell;
#[derive(Clone, Serialize, Deserialize)]
struct Todo {
id: u64,
title: String,
completed: bool,
}
#[derive(Default)]
struct AppState {
todos: Mutex<Vec<Todo>>,
next_id: Cell<u64>,
}
CRUD endpoints
async fn create_todo(
data: web::Data<AppState>,
body: web::Json<CreateTodoRequest>,
) -> HttpResponse {
let id = data.next_id.get();
data.next_id.set(id + 1);
let todo = Todo {
id,
title: body.title.clone(),
completed: false,
};
data.todos.lock().unwrap().push(todo);
HttpResponse::Created().json(serde_json::json!({ "created": true }))
}
async fn get_todos(data: web::Data<AppState>) -> HttpResponse {
let todos = data.todos.lock().unwrap().clone();
HttpResponse::Ok().json(todos)
}
async fn update_todo(
data: web::Data<AppState>,
path: web::Path<u64>,
body: web::Json<UpdateTodoRequest>,
) -> HttpResponse {
let id = path.into_inner();
let mut todos = data.todos.lock().unwrap();
if let Some(todo) = todos.iter_mut().find(|t| t.id == id) {
todo.title = body.title.clone();
todo.completed = body.completed.unwrap_or(todo.completed);
return HttpResponse::Ok().json(todo);
}
HttpResponse::NotFound().finish()
}
async fn delete_todo(
data: web::Data<AppState>,
path: web::Path<u64>,
) -> HttpResponse {
let id = path.into_inner();
let mut todos = data.todos.lock().unwrap();
let len_before = todos.len();
todos.retain(|t| t.id != id);
if todos.len() < len_before {
return HttpResponse::Ok().json(serde_json::json!({ "deleted": true }));
}
HttpResponse::NotFound().finish()
}
Det her er kernen i enhver orden API—fire simple endpoints der håndterer alt fra at oprette til at slette. Alt sammen type-sikkert, alt sammen med compile-time fejl i stedet for runtime overraskelser.
Hvad får du ud af det?
Lad mig være konkret: en tilsvarende API bygget i Node.js vil typisk bruge 2-10 MB RAM idle. Den samme API i Rust? Under 1 MB. Ved høj load ser du ingen garbage collection spikes, ingen uforklarlige latency stigninger—bare konstant, forudsigelig ydeevne.
Bundle-størrelsen er lille. Starttiden er øjeblikkelig. Memory footprint er minimal. Og vigtigst af alt: compileren fanger fejl, før de når produktion.
Actix-web giver dig det bedste fra begge verdener—Rusts ydeevne og sikkerhed, kombineret med et ergonomisk API der ikke føles som at kæmpe mod sproget. Det tager lidt tid at vænne sig til, men når det først klikker, vil du undre dig over, hvorfor du nogensinde tolererede noget andet.