Membangun REST API Minimal dengan FastAPI: dari Setup sampai Deployment

Lhuqita Fazry
Python FastAPI REST API Pydantic Deployment
Membangun REST API Minimal dengan FastAPI: dari Setup sampai Deployment

Memulai Proyek FastAPI dengan Uvicorn

Langkah pertama dalam membangun REST API dengan FastAPI adalah menyiapkan lingkungan pengembangan dan membuat struktur aplikasi paling dasar. FastAPI adalah framework Python modern yang dirancang khusus untuk membangun API dengan performa tinggi, sedangkan Uvicorn berperan sebagai ASGI server yang menjalankan aplikasi kita.

Kita mulai dengan menginstal kedua library ini melalui pip:

bashbash
pip install fastapi uvicorn

Output:

text
Successfully installed fastapi-0.136.1 uvicorn-0.46.0 pydantic-2.13.4 starlette-1.0.0 anyio-4.13.0 click-8.3.3 h11-0.16.0

Setelah instalasi selesai, buat file bernama main.py dan tulis kode berikut:

pythonpython
from fastapi import FastAPI

app = FastAPI(title="Items API")

@app.get("/")
def read_root():
    return {"message": "API FastAPI berjalan!"}

Output (test via TestClient):

text
GET /: 200
{'message': 'API FastAPI berjalan!'}

Untuk menjalankan server pengembangan, gunakan perintah berikut di terminal:

bashbash
uvicorn main:app --reload

Parameter main:app merujuk pada file main.py dan variabel app di dalamnya, sementara flag --reload mengaktifkan mode auto-reload sehingga server otomatis restart setiap kali kita mengubah kode. Ini sangat membantu selama proses development.

Setelah server berjalan, buka browser dan akses http://127.0.0.1:8000. Kita akan melihat response JSON {"message": "API FastAPI berjalan!"}. Yang menarik, FastAPI secara otomatis menyediakan dokumentasi interaktif Swagger UI di http://127.0.0.1:8000/docs. Dari sini kita bisa menguji setiap endpoint secara langsung tanpa perlu alat tambahan.

Mendefinisikan Schema Data dengan Pydantic

Pydantic adalah library validasi data yang menjadi fondasi utama FastAPI dalam mengelola request dan response. Dengan Pydantic, kita mendefinisikan struktur data menggunakan kelas Python standar dengan type hints, dan secara otomatis FastAPI akan memvalidasi data yang masuk sesuai dengan skema tersebut.

Mari kita buat model untuk resource Item yang akan kita gunakan di seluruh API:

pythonpython
from pydantic import BaseModel
from typing import Optional

class ItemCreate(BaseModel):
    name: str
    price: float
    description: Optional[str] = None
    is_offer: bool = False

class ItemResponse(BaseModel):
    id: int
    name: str
    price: float
    description: Optional[str] = None
    is_offer: bool = False

ItemCreate digunakan sebagai model untuk request body saat membuat item baru. Setiap field memiliki tipe data Python standar — str, float, bool — yang langsung berfungsi sebagai validator. Jika client mengirimkan price dalam bentuk teks, FastAPI akan menolaknya dengan response error 422 (Unprocessable Entity).

ItemResponse adalah model untuk response yang akan dikirim kembali ke client. Perhatikan field id yang hanya ada di response, bukan di request. Ini adalah pola umum dalam desain API: pisahkan schema input dan output agar lebih eksplisit dan aman.

Keunggulan utama dari pendekatan ini adalah dokumentasi OpenAPI yang dihasilkan secara otomatis. Setiap field, tipe data, dan constraint yang kita definisikan akan muncul di Swagger UI, membuat konsumen API kita tahu persis data apa yang harus dikirim.

Membangun CRUD Endpoint untuk Resource Management

Data Science with Python
Data Science • Beginner

Data Science with Python

Master the art of data analysis, visualization, and predictive modeling.

Daftar

Sekarang kita akan mengimplementasikan operasi CRUD (Create, Read, Update, Delete) untuk resource Item. Kita akan menggunakan list dan dictionary Python sebagai penyimpanan data in-memory yang sederhana. Ini cukup untuk memahami alur kerja API tanpa perlu menyiapkan database terlebih dahulu.

pythonpython
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List

app = FastAPI(title="Items API")

class ItemCreate(BaseModel):
    name: str
    price: float
    description: Optional[str] = None
    is_offer: bool = False

class ItemResponse(BaseModel):
    id: int
    name: str
    price: float
    description: Optional[str] = None
    is_offer: bool = False

items_db = {}
next_id = 1

@app.post("/items", response_model=ItemResponse, status_code=201)
def create_item(item: ItemCreate):
    global next_id
    new_item = item.model_dump()
    new_item["id"] = next_id
    items_db[next_id] = new_item
    next_id += 1
    return items_db[next_id - 1]

@app.get("/items", response_model=List[ItemResponse])
def list_items():
    return list(items_db.values())

@app.get("/items/{item_id}", response_model=ItemResponse)
def get_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    return items_db[item_id]

@app.put("/items/{item_id}", response_model=ItemResponse)
def update_item(item_id: int, item: ItemCreate):
    if item_id not in items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    updated_item = item.model_dump()
    updated_item["id"] = item_id
    items_db[item_id] = updated_item
    return items_db[item_id]

@app.delete("/items/{item_id}", status_code=204)
def delete_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    del items_db[item_id]

Output (test via TestClient — CRUD flow):

text
POST /items: 201
{'id': 1, 'name': 'Laptop', 'price': 15000000.0, 'description': 'Gaming laptop', 'is_offer': False}

GET /items: 200
[{'id': 1, 'name': 'Laptop', 'price': 15000000.0, 'description': 'Gaming laptop', 'is_offer': False}]

GET /items/1: 200
{'id': 1, 'name': 'Laptop', 'price': 15000000.0, 'description': 'Gaming laptop', 'is_offer': False}

PUT /items/1: 200
{'id': 1, 'name': 'Laptop Gaming', 'price': 17500000.0, 'description': 'Upgraded', 'is_offer': True}

DELETE /items/1: 204

GET /items (after delete): 200
[]

Mari kita pahami alur kerja setiap endpoint:

POST /items — Menerima data item dari request body, memvalidasinya melalui ItemCreate, menyimpannya ke dictionary dengan ID unik, dan mengembalikan data yang sudah tersimpan bersama ID-nya. Status code 201 menandakan resource berhasil dibuat.

GET /items — Mengembalikan seluruh item yang tersimpan dalam bentuk list. Parameter response_model=List[ItemResponse] memastikan output sesuai dengan schema response.

GET /items/{item_id} — Mencari item berdasarkan ID. Jika tidak ditemukan, kita langsung mengembalikan error 404 menggunakan HTTPException.

PUT /items/{item_id} — Memperbarui item yang sudah ada. Sama seperti GET, jika ID tidak ditemukan, response error akan dikembalikan.

DELETE /items/{item_id} — Menghapus item berdasarkan ID. Status code 204 berarti sukses tanpa response body.

Seluruh endpoint ini bisa diuji langsung melalui Swagger UI di /docs. FastAPI secara otomatis mengenali tipe data path parameter item_id: int dan query parameter jika ada, lalu memvalidasinya tanpa perlu kode tambahan.

Kode Python FastAPI yang menampilkan endpoint CRUD untuk manajemen data Item

Gambar: Ilustrasi pengembangan backend API dengan kode Python — Sumber: [Unsplash](https://unsplash.com/photos/XXMA-8fBB-g) — Lisensi: Unsplash License

Validasi Request dan Error Handling Terstruktur

API yang baik harus memberikan feedback yang jelas ketika terjadi kesalahan. FastAPI menyediakan berbagai mekanisme untuk menangani error secara terstruktur, mulai dari HTTPException bawaan hingga custom exception handler untuk format error yang konsisten.

pythonpython
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field

class ItemCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    price: float = Field(..., gt=0)
    description: Optional[str] = Field(None, max_length=500)
    is_offer: bool = False

@app.exception_handler(HTTPException)
def custom_http_exception_handler(request: Request, exc: HTTPException):
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "error": True,
            "status_code": exc.status_code,
            "message": exc.detail
        }
    )

@app.get("/items/{item_id}")
def get_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(
            status_code=404,
            detail=f"Item dengan ID {item_id} tidak ditemukan"
        )
    return items_db[item_id]

Output (test via TestClient — 404 error with custom handler):

text
GET /items/999: 404
{'error': True, 'status_code': 404, 'message': 'Item dengan ID 999 tidak ditemukan'}

Field dari Pydantic memberikan kontrol lebih detail dibanding type hints biasa. Kita bisa menetapkan constraint seperti min_length, max_length, dan gt (greater than). Jika client mengirim data yang melanggar constraint ini, FastAPI akan mengembalikan response error 422 secara otomatis dengan pesan yang menjelaskan field mana yang bermasalah.

HTTPException memungkinkan kita mengembalikan error dengan status code HTTP yang tepat — 404 untuk resource tidak ditemukan, 400 untuk bad request, dan 422 untuk validation error. Dengan custom exception handler, kita memastikan format error konsisten di seluruh endpoint. Ini penting karena konsumen API (frontend, aplikasi mobile) sangat bergantung pada struktur error yang dapat diprediksi.

Menjalankan Aplikasi untuk Production Deployment

Setelah aplikasi siap, kita perlu mengonfigurasinya untuk lingkungan production. Mode --reload hanya cocok untuk development karena menggunakan satu worker dan mengonsumsi resource tambahan untuk file watching. Untuk production, kita butuh gunicorn sebagai process manager dengan worker Uvicorn.

bashbash
pip install gunicorn

Output:

text
Successfully installed gunicorn-26.0.0 packaging-26.2

Jalankan aplikasi dengan perintah berikut:

bashbash
gunicorn main:app \
    --worker-class uvicorn.workers.UvicornWorker \
    --workers 4 \
    --bind 0.0.0.0:8000

Selain itu, kita bisa mengatur konfigurasi melalui environment variable agar lebih fleksibel saat deployment:

pythonpython
import os

HOST = os.getenv("HOST", "0.0.0.0")
PORT = int(os.getenv("PORT", "8000"))

Untuk containerisasi, berikut adalah Dockerfile minimal yang siap digunakan:

dockerdockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "main:app", \
     "--worker-class", "uvicorn.workers.UvicornWorker", \
     "--workers", "4", \
     "--bind", "0.0.0.0:8000"]

Perbedaan utama antara development dan production terletak pada jumlah worker dan stabilitas. Mode development dengan --reload menggunakan satu worker yang langsung merespon perubahan file. Mode production menggunakan beberapa worker (disarankan 2-4 per server) untuk menangani lebih banyak request konkuren, tanpa reload otomatis demi keamanan dan performa.

FastAPI memberikan pengalaman pengembangan API yang sangat produktif berkat validasi otomatis, dokumentasi Swagger built-in, dan performa yang mendekati framework Go atau Node.js. Untuk eksplorasi lebih dalam tentang integrasi database dengan SQLAlchemy, autentikasi, dan deployment ke cloud, bergabunglah di course Python Web Development Rumah Coding. Kami akan memandu dari dasar hingga production-ready.

Course Terkait

E-commerce Sales Dashboard
Premium Course Data Science

Data Science with Python

Master the art of data analysis, visualization, and predictive modeling.

Capstone Project

E-commerce Sales Dashboard

  • Data Cleaning Pipeline
  • Interactive Charts
  • Sales Forecasting Model
7 Weeks Beginner
Lihat Detail Course
GreenGuard: Intelligent Plant Disease Diagnosis Web App
Premium Course Machine Learning

Deep Learning Bootcamp

A beginner-friendly, highly interactive bootcamp designed to take you from foundational concepts to deploying real-world Artificial Intelligence applications. Through a completely project-based approach, you will master the core of Deep Learning, Artificial Neural Networks, and Computer Vision using Python and TensorFlow, ultimately building a professional-grade AI web application for your portfolio.

Capstone Project

GreenGuard: Intelligent Plant Disease Diagnosis Web App

  • Interactive Image Upload UI: A clean, user-friendly interface built with Streamlit that supports drag-and-drop image uploads directly from a computer or mobile phone.
  • Real-Time AI Inference: Utilizes a lightweight, optimized CNN model (like MobileNetV2) to process the image and return a diagnosis in seconds without heavy server load.
  • Confidence Scoring Dashboard: Visually displays the model's prediction probability (e.g., "95% confident this is Tomato Late Blight") using interactive progress bars or charts.
7 Weeks Intermediate
Lihat Detail Course
Domain-Specific AI Knowledge Assistant
Premium Course Machine Learning

LLM Bootcamp

This project-based bootcamp is designed for beginners to dive practically into the world of Large Language Models (LLMs). Through hands-on building, you will learn how to interact with top-tier AI APIs, master prompt engineering, orchestrate complex workflows using LangChain, and implement Retrieval-Augmented Generation (RAG) to query your own documents. By the end of this course, you will have the skills to build, test, and deploy a fully functional, custom AI web application.

Capstone Project

Domain-Specific AI Knowledge Assistant

  • Dynamic Document Processing: A sidebar interface allowing users to upload new PDF or TXT files, which the app automatically chunks, embeds, and stores in the vector database.
  • Context-Aware Chat UI: A modern chat interface built with Streamlit that maintains conversation history, allowing users to ask follow-up questions naturally.
  • Strict Guardrails (Anti-Hallucination): System instructions designed so the AI politely declines to answer questions that fall outside the context of the uploaded documents.
7 Weeks Beginner
Lihat Detail Course

Artikel Terkait