Desain sudah di tangan; sekarang kita mewujudkannya menjadi endpoint yang benar-benar merespons request. Chapter Pengenalan FastAPI pada Section Web Development sudah memperkenalkan kerangka framework-nya, dan Chapter Desain REST API barusan menetapkan bentuk URI untuk API manajemen tugas: koleksi /tugas, item /tugas/42, dan filter lewat query string. Chapter ini merangkai semuanya menjadi kerangka API yang utuh — path operations untuk tiap method, tiga sumber input yang dibaca FastAPI dari tanda tangan fungsi, serta cara menguji semuanya tanpa menjalankan server. Seluruh contoh diuji pada Python 3.12 dengan FastAPI 0.128.

Membangun Kerangka Aplikasi #

Kita butuh dua hal: instance FastAPI sebagai aplikasi, dan penyimpanan sementara berupa dictionary dalam memori (database sungguhan hadir pada proyek Proyek: REST API Manajemen Tugas). Simpan kode berikut sebagai main.py:

python
from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

tugas_db = {
    1: {"id": 1, "judul": "Belajar Python", "selesai": False},
    2: {"id": 2, "judul": "Belajar FastAPI", "selesai": True},
}
id_berikutnya = 3


@app.get("/tugas")
def daftar_tugas(selesai: bool | None = None):
    if selesai is None:
        return list(tugas_db.values())
    return [t for t in tugas_db.values() if t["selesai"] == selesai]


@app.get("/tugas/{task_id}")
def detail_tugas(task_id: int):
    return tugas_db[task_id]


@app.post("/tugas")
def buat_tugas(tugas: dict):
    global id_berikutnya
    id_baru = id_berikutnya
    tugas_db[id_baru] = {
        "id": id_baru,
        "judul": tugas.get("judul"),
        "selesai": tugas.get("selesai", False),
    }
    id_berikutnya += 1
    return tugas_db[id_baru]

Mari kita telaah cara kerjanya:

  1. Baris 13 (@app.get("/tugas")): decorator @app.get mendaftarkan fungsi sebagai path operation — pasangan antara path /tugas dan method GET, persis semantik koleksi pada tabel method di chapter sebelumnya.
  2. Baris 14 (selesai: bool | None = None): parameter yang tidak muncul di path template dan memiliki annotation bertipe sederhana otomatis dibaca dari query string — ?selesai=true. Union bool | None berarti filter opsional (materi chapter Union dan Optional Types).
  3. Baris 21 (task_id: int): nama parameter sama dengan bagian {task_id} pada path, jadi FastAPI membacanya dari path parameter dan mengonversinya ke int — "/tugas/2" menjadi 2.
  4. Baris 26 (tugas: dict): annotation dict memberi tahu FastAPI untuk membaca request body JSON mentah. Nilai kembalian fungsi (dictionary atau list) otomatis diserialisasi menjadi JSON.

Tiga Sumber Input dalam Satu Tanda Tangan #

Tidak ada konfigurasi terpisah — FastAPI menyimpulkan sumber setiap parameter dari path template dan annotation. Pola lengkapnya:

Bentuk parameterSumberContoh pemanggilan
task_id: int (nama ada di path)path parameterGET /tugas/2
selesai: bool | None = None (tidak ada di path)query parameterGET /tugas?selesai=true
tugas: dict / model Pydanticrequest bodyPOST /tugas dengan JSON

Menguji Tanpa Menjalankan Server #

TestClient dari fastapi.testclient memanggil aplikasi secara langsung melalui antarmuka ASGI — tidak ada port, tidak ada server yang harus dihentikan manual. Tambahkan baris berikut di akhir main.py:

python
client = TestClient(app)

print(client.get("/tugas").json())
print(client.get("/tugas?selesai=true").json())
print(client.get("/tugas/2").json())

r = client.post("/tugas", json={"judul": "Belajar REST", "selesai": False})
print(r.status_code, r.json())
print(client.get("/tugas/3").json())

Output yang Dihasilkan:

text
[{'id': 1, 'judul': 'Belajar Python', 'selesai': False}, {'id': 2, 'judul': 'Belajar FastAPI', 'selesai': True}]
[{'id': 2, 'judul': 'Belajar FastAPI', 'selesai': True}]
{'id': 2, 'judul': 'Belajar FastAPI', 'selesai': True}
200 {'id': 3, 'judul': 'Belajar REST', 'selesai': False}
{'id': 3, 'judul': 'Belajar REST', 'selesai': False}

Baris kedua membuktikan filter bekerja: hanya tugas dengan selesai: true yang dikembalikan. Baris keempat menunjukkan POST mengembalikan status 200 beserta tugas baru, dan baris kelima memastikan tugas tersebut tersimpan — bisa dibaca kembali lewat path parameter 3.

Menjalankan dengan uvicorn #

Untuk menjalankan aplikasi sungguhan, gunakan server ASGI uvicorn — pola yang sama dengan chapter Pengenalan WSGI dan ASGI:

bash
uvicorn main:app --reload

Argumen main:app berarti “dari file main.py, ambil objek app”, dan --reload memuat ulang kode secara otomatis saat file berubah — cocok untuk pengembangan. Begitu server berjalan, buka http://127.0.0.1:8000/docs untuk melihat dokumentasi interaktif yang dibangkitkan otomatis (pembahasan penuh ada di chapter OpenAPI dan API Documentation).