Konfiguracja projektu
Strukturyzowanie API
Konfiguracja projektu to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Budowanie interfejsu REST API w Rust
W tym kursie zbudujesz mały interfejs REST API w Rust. Używamy frameworka internetowego Axum, opartego na Tokio (asynchronicznym środowisku uruchomieniowym) i Tower (middleware). Jest ergonomiczny, bezpieczny typowo i szeroko stosowany w środowiskach produkcyjnych.
W tej pierwszej lekcji skonfigurujesz strukturę projektu, aby w kolejnych lekcjach można było dodać trasy, modele, bazę danych i testy.
Tworzenie projektu
Zacznij od Cargo. Projekt binarny udostępnia punkt wejścia src/main.rs:
cargo new rest_apitworzy folder.cd rest_apiprzechodzi do tego folderu.cargo runbuduje projekt i go uruchamia.
Są to polecenia powłoki i Cargo, a nie fragmenty kodu Rust gotowe do uruchomienia.
// terminal
// cargo new rest_api
// cd rest_api
// cargo runDodawanie zależności
Interfejs API w Axum potrzebuje kilku crate’ów w pliku Cargo.toml:
axumdo routingu i handlerów.tokiojako asynchroniczne środowisko uruchomieniowe.serdedo serializacji JSON.
// Cargo.toml
// [dependencies]
// axum = "0.7"
// tokio = { version = "1", features = ["full"] }
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"Asynchroniczne środowisko uruchomieniowe
Serwery internetowe obsługują wiele połączeń jednocześnie, dlatego Axum jest asynchroniczny. Atrybut #[tokio::main] zmienia asynchroniczną funkcję main w rzeczywisty punkt wejścia, uruchamiając środowisko uruchomieniowe Tokio. Każdy handler może używać .await do nieblokujących operacji wejścia-wyjścia.
// src/main.rs
use tokio;
#[tokio::main]
async fn main() {
println!("runtime started");
}Minimalny serwer
Najmniejsza aplikacja Axum tworzy Router, wiąże nasłuchujący port TCP i uruchamia serwer. Pojedyncza trasa mapuje GET / na handler zwracający ciąg znaków. Handlery to zwykłe funkcje asynchroniczne zwracające wartość implementującą 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!"
}Jak działa routing
Obiekt Router mapuje ścieżkę i metodę HTTP na handler. Łącz wywołania .route(path, method(handler)), aby rejestrować endpointy. Pomocnicze funkcje metod, takie jak get, post, put i delete, pochodzą z axum::routing. Możesz łączyć metody dla tej samej ścieżki.
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" }))
}Zalecany układ modułów
W miarę rozrastania się interfejsu API podziel kod na moduły zamiast umieszczać wszystko w jednym ogromnym pliku main.rs:
main.rs— uruchamianie i konfiguracja serwera.routes.rs— definicja routera.handlers.rs— handlery żądań.models.rs— struktury danych.
Taki podział pozwala zachować przejrzystość każdego pliku i ułatwia jego testowanie.
// 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();
}Współdzielony stan aplikacji
Większość interfejsów API potrzebuje współdzielonego stanu, takiego jak pula połączeń z bazą danych lub magazyn w pamięci. Axum przechowuje go za pomocą .with_state(state) na routerze. Handlery otrzymują go przez ekstraktor State. Stan musi implementować Clone; dane modyfikowalne należy opakować w Arc i blokadę.
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)
}Zwracanie JSON
Aby wysłać JSON, opakuj wartość możliwą do serializacji w axum::Json. Gdy struktury mają wyprowadzoną implementację Serialize za pomocą serde, Axum automatycznie ustawia właściwy typ zawartości i treść odpowiedzi.
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 })
}Konfiguracja i porty
Zakodowanie portu na stałe jest odpowiednie w demonstracjach, ale rzeczywiste usługi odczytują konfigurację ze środowiska. Użyj std::env::var wraz z wartością domyślną. Dzięki temu można zmienić adres nasłuchiwania bez ponownej kompilacji i zapewnić poprawną współpracę z kontenerami.
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 ...
}Łączenie konfiguracji
Kompletna konfiguracja uruchomieniowa łączy wszystkie elementy: buduje router z trasami i współdzielonym stanem, odczytuje port, wiąże nasłuchujący port i uruchamia serwer. Mając ten szkielet, w kolejnych lekcjach dodasz rzeczywiste endpointy, modele i trwałe przechowywanie danych.
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();
}Szybkie sprawdzenie
Sprawdź swoją wiedzę o konfiguracji projektu.
Podsumowanie
Skonfigurowano projekt interfejsu REST API w Rust:
- Użyj
cargo newi dodajaxum,tokioorazserde. #[tokio::main]zapewnia asynchroniczne środowisko uruchomieniowe.- Obiekt
Routermapuje ścieżki i metody na asynchroniczne handlery. - Udostępniaj dane za pomocą
.with_statei ekstraktoraState. - Podziel kod na moduły tras, handlerów i modeli; odczytuj port ze środowiska.
Często zadawane pytania
Czy lekcja „Konfiguracja projektu” jest bezpłatna?
Tak — pełny tekst „Konfiguracja projektu” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Co nauczysz się w „Konfiguracja projektu”?
Strukturyzowanie API Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?
Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Konfiguracja projektu”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?
Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Konfiguracja projektu
- Endpointy i modele
- Integracja z bazą danych
- Testowanie API