Web Server #

Python memiliki ekosistem web server yang kaya — dari modul bawaan untuk kebutuhan sederhana, hingga framework lengkap untuk aplikasi skala produksi. Memilih yang tepat bergantung pada kompleksitas proyek, kebutuhan performa, dan seberapa banyak “baterai” yang kamu inginkan sudah terpasang. Artikel ini membahas empat pilihan utama dengan contoh yang cukup nyata untuk menunjukkan karakter masing-masing: http.server, Flask, FastAPI, dan Django.

WSGI vs ASGI #

Sebelum memilih framework, penting memahami dua model interface web Python karena ini mempengaruhi performa dan ekosistem deployment.

WSGI (Web Server Gateway Interface)    ASGI (Asynchronous SGI)
────────────────────────────────────   ──────────────────────────
Model: synchronous                     Model: asynchronous (async/await)
Server: Gunicorn, uWSGI                Server: Uvicorn, Hypercorn, Daphne
Framework: Flask, Django               Framework: FastAPI, Django (3.0+), Starlette
Cocok: request-response biasa          Cocok: WebSocket, long-polling, streaming
Concurrency: multi-process/thread      Concurrency: event loop (lebih efisien I/O)

http.server — Server Development Cepat #

Modul bawaan Python, tidak perlu instalasi apapun. Berguna untuk menyajikan file statis sementara saat development — bukan untuk production.

import http.server
import socketserver

PORT = 8000

# SimpleHTTPRequestHandler: sajikan file dari direktori saat ini
with socketserver.TCPServer(("", PORT), http.server.SimpleHTTPRequestHandler) as httpd:
    print(f"Serving di http://localhost:{PORT}")
    httpd.serve_forever()

Atau langsung dari terminal tanpa menulis kode:

# Python 3 — sajikan direktori saat ini di port 8000
python -m http.server 8000

# Tentukan direktori spesifik
python -m http.server 8000 --directory /path/ke/folder
http.server tidak cocok untuk production — tidak ada autentikasi, tidak ada keamanan, dan performanya sangat terbatas. Gunakan hanya untuk development lokal atau berbagi file sementara di jaringan internal.

Flask — Microframework Fleksibel #

Flask memberikan kamu fondasi minimal: routing dan request/response handling. Sisanya kamu pilih sendiri — database, autentikasi, validasi. Cocok untuk REST API sederhana hingga menengah, atau saat kamu ingin kontrol penuh atas arsitektur.

pip install flask

Routing dan Response #

from flask import Flask, request, jsonify, abort

app = Flask(__name__)

# Data simulasi (normalnya dari database)
produk_db = {
    1: {"id": 1, "nama": "Laptop", "harga": 12000000},
    2: {"id": 2, "nama": "Mouse", "harga": 250000},
}

@app.route("/produk", methods=["GET"])
def daftar_produk():
    """GET /produk — kembalikan semua produk."""
    return jsonify(list(produk_db.values()))

@app.route("/produk/<int:produk_id>", methods=["GET"])
def detail_produk(produk_id):
    """GET /produk/:id — kembalikan satu produk berdasarkan ID."""
    produk = produk_db.get(produk_id)
    if produk is None:
        abort(404)  # Flask akan kembalikan respons 404 otomatis
    return jsonify(produk)

@app.route("/produk", methods=["POST"])
def tambah_produk():
    """POST /produk — tambah produk baru dari JSON body."""
    data = request.get_json()
    if not data or "nama" not in data or "harga" not in data:
        return jsonify({"error": "Field 'nama' dan 'harga' wajib diisi."}), 400

    id_baru = max(produk_db.keys()) + 1
    produk_baru = {"id": id_baru, "nama": data["nama"], "harga": data["harga"]}
    produk_db[id_baru] = produk_baru
    return jsonify(produk_baru), 201  # 201 Created

@app.route("/produk/<int:produk_id>", methods=["DELETE"])
def hapus_produk(produk_id):
    """DELETE /produk/:id — hapus produk."""
    if produk_id not in produk_db:
        abort(404)
    del produk_db[produk_id]
    return "", 204  # 204 No Content

if __name__ == "__main__":
    # debug=True hanya untuk development — matikan di production!
    app.run(host="0.0.0.0", port=5000, debug=True)

Penanganan Error Terpusat #

@app.errorhandler(404)
def tidak_ditemukan(error):
    return jsonify({"error": "Resource tidak ditemukan."}), 404

@app.errorhandler(500)
def server_error(error):
    return jsonify({"error": "Terjadi kesalahan internal server."}), 500
Jangan gunakan app.run() di production. Server development Flask single-threaded dan tidak aman. Untuk production, jalankan Flask dengan WSGI server seperti Gunicorn: gunicorn -w 4 -b 0.0.0.0:5000 app:app (4 worker process).

FastAPI — API Modern dengan Type Hints #

FastAPI memanfaatkan type hints Python untuk validasi input otomatis, serialisasi response, dan dokumentasi interaktif yang di-generate secara otomatis. Performanya setara dengan Node.js dan Go untuk I/O-bound tasks berkat ASGI.

pip install fastapi uvicorn

Routing, Validasi, dan Dokumentasi Otomatis #

from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field
from typing import Optional

app = FastAPI(title="API Produk", version="1.0.0")

# Pydantic model: definisi sekaligus validasi dan dokumentasi
class ProdukCreate(BaseModel):
    nama: str = Field(..., min_length=1, max_length=100, description="Nama produk")
    harga: int = Field(..., gt=0, description="Harga dalam rupiah, harus positif")
    stok: Optional[int] = Field(default=0, ge=0)

class Produk(ProdukCreate):
    id: int

# Data simulasi
produk_db: dict[int, Produk] = {
    1: Produk(id=1, nama="Laptop", harga=12000000, stok=5),
    2: Produk(id=2, nama="Mouse", harga=250000, stok=20),
}

@app.get("/produk", response_model=list[Produk])
def daftar_produk(skip: int = 0, limit: int = 10):
    """
    Ambil daftar produk dengan pagination.
    - **skip**: jumlah item yang dilewati
    - **limit**: jumlah item maksimal yang dikembalikan
    """
    items = list(produk_db.values())
    return items[skip : skip + limit]

@app.get("/produk/{produk_id}", response_model=Produk)
def detail_produk(produk_id: int):
    """Ambil detail satu produk berdasarkan ID."""
    if produk_id not in produk_db:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Produk dengan ID {produk_id} tidak ditemukan."
        )
    return produk_db[produk_id]

@app.post("/produk", response_model=Produk, status_code=status.HTTP_201_CREATED)
def tambah_produk(produk: ProdukCreate):
    """
    Tambah produk baru.
    FastAPI otomatis memvalidasi body request berdasarkan ProdukCreate.
    Jika validasi gagal, 422 Unprocessable Entity dikembalikan otomatis.
    """
    id_baru = max(produk_db.keys()) + 1
    produk_baru = Produk(id=id_baru, **produk.model_dump())
    produk_db[id_baru] = produk_baru
    return produk_baru

@app.delete("/produk/{produk_id}", status_code=status.HTTP_204_NO_CONTENT)
def hapus_produk(produk_id: int):
    """Hapus produk berdasarkan ID."""
    if produk_id not in produk_db:
        raise HTTPException(status_code=404, detail="Produk tidak ditemukan.")
    del produk_db[produk_id]

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

Setelah server jalan, FastAPI menyediakan dokumentasi interaktif secara otomatis:

  • Swagger UI: http://localhost:8000/docs
  • ReDoc: http://localhost:8000/redoc
FastAPI menggunakan Pydantic untuk validasi — jika request body tidak sesuai schema, FastAPI otomatis mengembalikan 422 Unprocessable Entity dengan detail field mana yang salah, tanpa kamu perlu menulis kode validasi manual.

Django hadir dengan “batteries included”: ORM, admin panel, autentikasi, form handling, migrations — semuanya sudah tersedia. Cocok untuk aplikasi web kompleks yang butuh banyak fitur siap pakai.

pip install django djangorestframework

Membuat Proyek dan Aplikasi #

django-admin startproject toko .    # buat proyek (titik = di direktori saat ini)
python manage.py startapp produk    # buat aplikasi
python manage.py migrate            # jalankan migrasi awal
python manage.py runserver          # jalankan development server

Struktur proyek yang dihasilkan:

toko/
  ├── manage.py
  ├── toko/
  │   ├── settings.py      ← konfigurasi proyek
  │   ├── urls.py          ← routing utama
  │   └── wsgi.py
  └── produk/
      ├── models.py        ← definisi model/tabel database
      ├── views.py         ← logika request/response
      ├── urls.py          ← routing aplikasi
      └── admin.py         ← konfigurasi admin panel

Contoh Model dan View Sederhana #

# produk/models.py
from django.db import models

class Produk(models.Model):
    nama = models.CharField(max_length=100)
    harga = models.PositiveIntegerField()
    stok = models.PositiveIntegerField(default=0)
    dibuat_pada = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.nama

    class Meta:
        ordering = ["-dibuat_pada"]
# produk/views.py — menggunakan Django REST Framework
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import serializers
from .models import Produk

class ProdukSerializer(serializers.ModelSerializer):
    class Meta:
        model = Produk
        fields = "__all__"

class ProdukViewSet(viewsets.ModelViewSet):
    """
    ViewSet otomatis menyediakan:
    GET    /produk/       → list semua produk
    POST   /produk/       → tambah produk baru
    GET    /produk/{id}/  → detail satu produk
    PUT    /produk/{id}/  → update produk
    DELETE /produk/{id}/  → hapus produk
    """
    queryset = Produk.objects.all()
    serializer_class = ProdukSerializer
# Buat dan jalankan migrasi setelah mendefinisikan model
python manage.py makemigrations produk
python manage.py migrate

Perbandingan dan Panduan Memilih #

                http.server   Flask         FastAPI       Django
                ──────────    ──────────    ──────────    ──────────
Tujuan          File statis   REST API      REST API      Full-stack
Interface       WSGI          WSGI          ASGI          WSGI/ASGI
Kurva belajar   Sangat mudah  Mudah         Mudah-sedang  Sedang-tinggi
Validasi input  ✗             Manual        Otomatis      Otomatis (DRF)
Dokumentasi API ✗             Manual        Otomatis      Manual/DRF
ORM bawaan      ✗             ✗             ✗             ✓
Admin panel     ✗             ✗             ✗             ✓
Production      ✗             Gunicorn      Uvicorn       Gunicorn/Uvicorn
Pilih Flask jika:
  ✓ Butuh REST API sederhana dengan kontrol penuh
  ✓ Tim sudah familiar dengan Flask
  ✓ Tidak butuh validasi otomatis atau dokumentasi
  ✓ Butuh fleksibilitas memilih komponen sendiri

Pilih FastAPI jika:
  ✓ Butuh REST API dengan validasi ketat dan dokumentasi otomatis
  ✓ Performa tinggi untuk I/O-bound tasks
  ✓ Tim nyaman dengan type hints dan async/await
  ✓ Ingin API docs (Swagger) tanpa effort tambahan

Pilih Django jika:
  ✓ Butuh aplikasi web lengkap: auth, admin, ORM, form
  ✓ Ingin "batteries included" tanpa merakit sendiri
  ✓ Proyek skala besar dengan tim yang besar
  ✓ Butuh admin panel yang bisa dikustomisasi

Ringkasan #

  • http.server hanya untuk development lokal — tidak aman dan tidak performan untuk production.
  • Flask adalah microframework WSGI yang fleksibel — kamu pilih sendiri semua komponennya; cocok untuk REST API sederhana hingga menengah.
  • FastAPI adalah framework ASGI modern — validasi input otomatis via Pydantic, dokumentasi Swagger auto-generated, dan performa tinggi; cocok untuk API yang perlu type safety dan developer experience terbaik.
  • Django hadir dengan semua fitur siap pakai — ORM, admin, autentikasi, migrations; cocok untuk aplikasi web kompleks yang butuh produktivitas tinggi dari awal.
  • Jangan gunakan app.run() Flask di production — gunakan Gunicorn untuk WSGI, Uvicorn untuk ASGI.
  • WSGI (Flask, Django) untuk request-response sinkron; ASGI (FastAPI, Django 3+) untuk WebSocket, streaming, dan async handler.
  • Pilih framework berdasarkan kebutuhan proyek, bukan popularitas — masing-masing punya trade-off yang berbeda.

← Sebelumnya: Web Socket   Berikutnya: Unit Test →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact