Configurazione del progetto
Strutturare l'API
Configurazione del progetto è una lezione Learn Rust Coding gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Learn Rust Coding, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Learn Rust Coding include 4 lezioni in totale.
Costruire una REST API in Rust
In questo corso costruirete una piccola REST API in Rust. Useremo il framework web Axum, basato su Tokio (runtime asincrono) e Tower (middleware). È ergonomico, type-safe e ampiamente utilizzato in produzione.
Questa prima lezione configura la struttura del progetto, così nelle lezioni successive sarà possibile aggiungere route, modelli, un database e test.
Creare il progetto
Iniziate con Cargo. Un progetto binario offre un punto di ingresso src/main.rs:
cargo new rest_apicrea la cartella.cd rest_apivi sposta al suo interno.cargo runesegue la compilazione e l'avvio.
Questi sono comandi della shell e di cargo, non frammenti Rust eseguibili.
// terminal
// cargo new rest_api
// cd rest_api
// cargo runAggiungere le dipendenze
Un'API Axum richiede alcuni crate in Cargo.toml:
axumper il routing e gli handler.tokioper il runtime asincrono.serdeper la serializzazione JSON.
// Cargo.toml
// [dependencies]
// axum = "0.7"
// tokio = { version = "1", features = ["full"] }
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"Il runtime asincrono
I server web gestiscono molte connessioni simultaneamente, quindi Axum è async. L'attributo #[tokio::main] trasforma un main asincrono in un vero punto di ingresso avviando il runtime Tokio. Ogni handler può usare .await per eseguire I/O non bloccante.
// src/main.rs
use tokio;
#[tokio::main]
async fn main() {
println!("runtime started");
}Un server minimale
L'applicazione Axum più semplice crea un Router, associa un listener TCP e avvia il server. Un'unica route associa GET / a un handler che restituisce una stringa. Gli handler sono semplicemente funzioni asincrone che restituiscono un valore che implementa IntoResponse.
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(root));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn root() -> &'static str {
"Hello, API!"
}Come funziona il routing
Un Router associa un percorso e un metodo HTTP a un handler. Concatenate le chiamate .route(path, method(handler)) per registrare gli endpoint. Gli helper per i metodi, come get, post, put e delete, provengono da axum::routing. Potete combinare più metodi sullo stesso percorso.
use axum::{routing::{get, post}, Router};
async fn list() -> &'static str { "list" }
async fn create() -> &'static str { "created" }
fn build_router() -> Router {
Router::new()
.route("/items", get(list).post(create))
.route("/health", get(|| async { "ok" }))
}Struttura consigliata dei moduli
Quando l'API cresce, suddividete il codice in moduli invece di concentrarlo in un unico enorme main.rs:
main.rs— avvio e configurazione del server.routes.rs— definizione del router.handlers.rs— handler delle richieste.models.rs— strutture dati.
Questa separazione mantiene ogni file focalizzato e facilmente testabile.
// src/main.rs
mod routes;
mod handlers;
mod models;
#[tokio::main]
async fn main() {
let app = routes::build();
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await.unwrap();
axum::serve(listener, app).await.unwrap();
}Stato condiviso dell'applicazione
La maggior parte delle API richiede uno stato condiviso, ad esempio un pool di connessioni al database o un archivio in memoria. Axum lo mantiene con .with_state(state) sul router. Gli handler lo ricevono tramite l'estrattore State. Lo stato deve essere Clone; racchiudete i dati mutabili in un Arc e in un lock.
use axum::{routing::get, Router, extract::State};
use std::sync::{Arc, Mutex};
type Db = Arc<Mutex<Vec<String>>>;
async fn count(State(db): State<Db>) -> String {
let n = db.lock().unwrap().len();
format!("{} items", n)
}
fn build(db: Db) -> Router {
Router::new().route("/count", get(count)).with_state(db)
}Restituire JSON
Per inviare JSON, racchiudete un valore serializzabile in axum::Json. Se usate serde per derivare Serialize sulle vostre struct, Axum imposta automaticamente il tipo di contenuto e il body corretti.
use axum::Json;
use serde::Serialize;
#[derive(Serialize)]
struct Status {
service: String,
healthy: bool,
}
async fn health() -> Json<Status> {
Json(Status { service: "api".into(), healthy: true })
}Configurazione e porte
Impostare la porta direttamente nel codice va bene per le demo, ma i servizi reali leggono la configurazione dall'ambiente. Usate std::env::var con un valore predefinito. In questo modo potete cambiare l'indirizzo di binding senza ricompilare e lavorare meglio con i container.
use std::env;
async fn main_inner() {
let port = env::var("PORT").unwrap_or_else(|_| "3000".to_string());
let addr = format!("0.0.0.0:{}", port);
println!("binding to {}", addr);
// bind and serve with addr ...
}Completare la configurazione
Un avvio completo collega tutti gli elementi: create il router con le route e lo stato condiviso, leggete la porta, associate un listener e avviate il server. Con questa struttura di base, nelle lezioni successive aggiungerete endpoint, modelli e persistenza reali.
use axum::{routing::get, Router};
use std::sync::{Arc, Mutex};
#[tokio::main]
async fn main() {
let db = Arc::new(Mutex::new(Vec::<String>::new()));
let app = Router::new()
.route("/health", get(|| async { "ok" }))
.with_state(db);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await.unwrap();
axum::serve(listener, app).await.unwrap();
}Verifica rapida
Verificate la vostra comprensione della configurazione del progetto.
Riepilogo
Avete configurato un progetto di API REST in Rust:
- Usate
cargo newe aggiungeteaxum,tokioeserde. #[tokio::main]fornisce il runtime asincrono.- Un
Routerassocia percorsi e metodi a handler asincroni. - Condividete i dati con
.with_statee l'estrattoreState. - Suddividete il codice in moduli per route, handler e modelli; leggete la porta dall'ambiente.
Domande Frequenti
La lezione «Configurazione del progetto» è gratuita?
Sì — il testo completo di «Configurazione del progetto» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Learn Rust Coding, passa a CoddyKit PRO. Il corso Learn Rust Coding include 4 lezioni in totale.
Cosa imparerò in «Configurazione del progetto»?
Strutturare l'API Eserciti Learn Rust Coding con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Learn Rust Coding?
Non è richiesta alcuna esperienza precedente. Learn Rust Coding su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Configurazione del progetto»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Learn Rust Coding?
Sì. Ogni lezione Learn Rust Coding include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Configurazione del progetto
- Endpoint e modelli
- Integrazione con il database
- Test dell'API