Endpoint dan Model
Rute dan data
Endpoint dan Model adalah pelajaran Learn Rust Coding gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Learn Rust Coding, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Learn Rust Coding mencakup 4 pelajaran total.
Route dan Model Data
API ditentukan oleh endpoint-nya (URL beserta metode HTTP) dan model (bentuk data) yang mengalir melaluinya. Dalam pelajaran ini, Anda akan mendefinisikan model permintaan dan respons dengan serde, lalu menghubungkan route bergaya CRUD di Axum.
Mendefinisikan Model
Model adalah struct Rust biasa. Turunkan Serialize agar model dapat menjadi JSON dalam respons dan Deserialize agar dapat diuraikan dari body permintaan. Nama field dipetakan langsung ke kunci JSON.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone)]
struct Todo {
id: u32,
title: String,
done: bool,
}Memisahkan Tipe Permintaan dan Respons
Klien tidak seharusnya mengirim id yang ditetapkan server saat membuat sumber daya. Gunakan struct input terpisah untuk body permintaan dan model lengkap untuk respons. Dengan demikian, kontrak tetap jelas dan klien tidak dapat menetapkan field yang seharusnya tidak mereka ubah.
use serde::Deserialize;
#[derive(Deserialize)]
struct CreateTodo {
title: String,
}
// The handler assigns the id and sets done = false.GET: Menampilkan Sumber Daya
Handler GET /todos mengembalikan seluruh koleksi sebagai array JSON. Handler ini membaca state bersama, menyalin data keluar dari lock dengan cepat, lalu membungkusnya dalam Json.
use axum::{extract::State, Json};
use std::sync::{Arc, Mutex};
type Store = Arc<Mutex<Vec<Todo>>>;
#[derive(Clone, serde::Serialize)]
struct Todo { id: u32, title: String, done: bool }
async fn list_todos(State(store): State<Store>) -> Json<Vec<Todo>> {
let todos = store.lock().unwrap().clone();
Json(todos)
}POST: Membuat Sumber Daya
Handler POST /todos membaca body JSON dengan extractor Json, menetapkan id baru, menyimpan item, lalu mengembalikannya dengan status 201 Created. Tuple (StatusCode, Json<T>) memungkinkan Anda menetapkan status dan body sekaligus.
use axum::{extract::State, Json, http::StatusCode};
async fn create_todo(
State(store): State<Store>,
Json(input): Json<CreateTodo>,
) -> (StatusCode, Json<Todo>) {
let mut todos = store.lock().unwrap();
let id = todos.len() as u32 + 1;
let todo = Todo { id, title: input.title, done: false };
todos.push(todo.clone());
(StatusCode::CREATED, Json(todo))
}Parameter Path
Untuk mengambil satu sumber daya, tangkap bagian URL dengan parameter path. Deklarasikan parameter tersebut dalam route sebagai /todos/{id} dan ekstrak dengan extractor Path. Tipe yang diminta (dalam contoh ini u32) diuraikan secara otomatis.
use axum::extract::{Path, State};
use axum::{Json, http::StatusCode};
async fn get_todo(
State(store): State<Store>,
Path(id): Path<u32>,
) -> Result<Json<Todo>, StatusCode> {
let todos = store.lock().unwrap();
match todos.iter().find(|t| t.id == id) {
Some(t) => Ok(Json(t.clone())),
None => Err(StatusCode::NOT_FOUND),
}
}Parameter Query
Pemfilteran dan pagination menggunakan query string, seperti /todos?done=true. Tangkap query tersebut dengan extractor Query ke dalam struct Deserialize. Field opsional menggunakan Option sehingga parameter yang tidak ada tetap dapat diterima.
use axum::extract::{Query, State};
use axum::Json;
use serde::Deserialize;
#[derive(Deserialize)]
struct Filter { done: Option<bool> }
async fn filtered(
State(store): State<Store>,
Query(f): Query<Filter>,
) -> Json<Vec<Todo>> {
let todos = store.lock().unwrap();
let out = todos.iter()
.filter(|t| f.done.map_or(true, |d| t.done == d))
.cloned().collect();
Json(out)
}PUT dan DELETE
Pembaruan menggunakan PUT /todos/{id} dengan body; penghapusan menggunakan DELETE /todos/{id}. Keduanya mencari item berdasarkan id dan mengembalikan 404 jika item tidak ditemukan. Delete biasanya mengembalikan 204 No Content jika berhasil.
use axum::extract::{Path, State};
use axum::http::StatusCode;
async fn delete_todo(
State(store): State<Store>,
Path(id): Path<u32>,
) -> StatusCode {
let mut todos = store.lock().unwrap();
let before = todos.len();
todos.retain(|t| t.id != id);
if todos.len() < before { StatusCode::NO_CONTENT }
else { StatusCode::NOT_FOUND }
}Menghubungkan Semua Route
Daftarkan setiap handler pada router. Kelompokkan metode pada path yang sama: /todos menangani daftar dan pembuatan, sedangkan /todos/{id} menangani pengambilan, pembaruan, dan penghapusan. Lampirkan penyimpanan bersama dengan .with_state.
use axum::{routing::get, Router};
fn build(store: Store) -> Router {
Router::new()
.route("/todos", get(list_todos).post(create_todo))
.route("/todos/{id}",
get(get_todo).delete(delete_todo))
.with_state(store)
}Memvalidasi Input
Jangan pernah mempercayai data dari klien. Periksa data tersebut di dalam handler dan kembalikan 400 Bad Request jika tidak valid. Di sini, kami menolak judul kosong sebelum menyimpan apa pun agar data buruk tidak masuk ke sistem.
use axum::{Json, extract::State, http::StatusCode};
async fn create_validated(
State(store): State<Store>,
Json(input): Json<CreateTodo>,
) -> Result<(StatusCode, Json<Todo>), StatusCode> {
if input.title.trim().is_empty() {
return Err(StatusCode::BAD_REQUEST);
}
let mut todos = store.lock().unwrap();
let id = todos.len() as u32 + 1;
let todo = Todo { id, title: input.title, done: false };
todos.push(todo.clone());
Ok((StatusCode::CREATED, Json(todo)))
}Respons Error yang Konsisten
Mengembalikan kode status saja memang dapat dilakukan, tetapi API produksi juga mengembalikan body error JSON. Pendekatan umum adalah enum error khusus yang mengimplementasikan IntoResponse, dengan memetakan setiap varian ke status dan pesan. Dengan begitu, klien menerima error yang konsisten dan dapat dibaca mesin.
use axum::response::{IntoResponse, Response};
use axum::http::StatusCode;
use axum::Json;
use serde_json::json;
enum ApiError { NotFound, BadRequest(String) }
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let (status, msg) = match self {
ApiError::NotFound => (StatusCode::NOT_FOUND, "not found".to_string()),
ApiError::BadRequest(m) => (StatusCode::BAD_REQUEST, m),
};
(status, Json(json!({ "error": msg }))).into_response()
}
}Pemeriksaan Singkat
Uji pemahaman Anda tentang endpoint dan model.
Ringkasan
Anda telah mendefinisikan endpoint dan model:
- Model adalah struct yang menurunkan
Serialize/Deserialize; gunakan tipe input terpisah. Json,Path,Query, danStatemengekstrak data permintaan.- Petakan CRUD ke GET/POST/PUT/DELETE dengan kode status yang sesuai.
- Validasi input dan kembalikan
400untuk data yang tidak valid. - Tipe error khusus yang mengimplementasikan
IntoResponsemenghasilkan error JSON yang konsisten.
Belajar Rust dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 39
- Pelajaran
- 144
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Endpoint dan Model” gratis?
Ya — teks lengkap “Endpoint dan Model” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Learn Rust Coding, upgrade ke CoddyKit PRO. Kursus Learn Rust Coding mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Endpoint dan Model”?
Rute dan data Kamu berlatih Learn Rust Coding dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Learn Rust Coding?
Tidak diperlukan pengalaman sebelumnya. Learn Rust Coding di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.
Berapa lama pelajaran “Endpoint dan Model” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Learn Rust Coding ini?
Ya. Setiap pelajaran Learn Rust Coding menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Penyiapan Proyek
- Endpoint dan Model
- Integrasi Database
- Menguji API