Dipublikasikan 11 Juni 2026
Memahami cara kerja web server dari fundamental adalah keterampilan yang semakin langka di era framework dan platform-as-a-service. Banyak developer bisa deploy aplikasi dengan sekali klik, tetapi sedikit yang paham bagaimana request HTTP benar-benar diproses dari bit pertama yang masuk melalui network interface. Repository Build Your Own X dari CodeCrafters mengkurasi tutorial-tutorial berkualitas untuk membangun teknologi populer dari nol, termasuk web server. Artikel ini mengadaptasi konsep tersebut menjadi panduan praktis menggunakan Python dan TCP socket.
Belajar membangun web server dari nol bukan latihan akademis belaka. Pengetahuan ini menjadi krusial saat debugging networking issue, optimasi performa, atau bahkan membangun custom proxy dan load balancer. Developer yang memahami lapisan transport dan application protocol akan lebih percaya diri saat menghadapi masalah infrastruktur di production.
Sebelum menulis kode, pahami komponen dasar web server. Secara minimal, server harus mampu: membuka socket pada port tertentu, menerima koneksi TCP dari client, membaca HTTP request, memproses request sesuai method dan path, lalu mengirimkan HTTP response dengan header dan body yang sesuai.
Web server modern seperti Nginx atau Apache menambahkan banyak lapisan: reverse proxy, load balancing, SSL termination, caching, dan compression. Namun, inti dari semua fitur tersebut tetap sama: menerima koneksi TCP, parse HTTP, dan kirim response. Tutorial ini akan membangun inti tersebut dengan kurang dari 200 baris kode Python.
Tutorial ini menggunakan Python 3.10+ tanpa library eksternal. Semua modul yang digunakan berasal dari standard library: socket, threading, dan os. Pastikan Python sudah terinstall dan terminal bisa mengakses interpreter melalui command python3.
Buat direktori proyek baru dengan struktur berikut:
webserver/
├── server.py
├── handlers.py
└── static/
└── index.htmlFile server.py akan berisi logic utama socket dan HTTP parsing. File handlers.py berisi routing dan business logic. Direktori static menyimpan file HTML yang bisa di-serve langsung.
Langkah pertama adalah membuat TCP socket yang listen pada port tertentu. Berikut implementasi dasar di server.py:
import socket
def start_server(host='127.0.0.1', port=8080):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((host, port))
server_socket.listen(5)
print(f'Server listening on {host}:{port}')
while True:
client_socket, address = server_socket.accept()
print(f'Connection from {address}')
handle_request(client_socket)
if __name__ == '__main__':
start_server()Fungsi socket.socket membuat endpoint komunikasi. SO_REUSEADDR memungkinkan socket untuk segera reusable setelah server direstart. listen(5) mengatur backlog queue untuk connection yang belum di-accept. Saat ini, server hanya mencetak alamat client dan menutup koneksi. Langkah berikutnya adalah menambahkan HTTP parsing.
HTTP request yang masuk melalui socket adalah sekadar byte stream. Server harus memecah stream tersebut menjadi komponen: request line, header, dan body. Request line berisi method, path, dan versi HTTP. Header berisi pasangan key-value yang dipisahkan oleh colon.
Tambahkan fungsi parsing di server.py:
def parse_request(data):
lines = data.decode('utf-8').split('\r\n')
request_line = lines[0].split()
method = request_line[0]
path = request_line[1]
version = request_line[2]
headers = {}
for line in lines[1:]:
if ':' in line:
key, value = line.split(':', 1)
headers[key.strip()] = value.strip()
return {'method': method, 'path': path, 'version': version, 'headers': headers}Fungsi ini meng-decode byte stream menjadi string, memisahkan berdasarkan line ending CRLF, lalu mengekstrak method, path, dan header. Perhatikan bahwa HTTP/1.1 mensyaratkan CRLF (\r\n) sebagai line terminator. Parsing ini masih sederhana dan tidak menangani edge case seperti chunked encoding atau multipart body.
Setelah request ter-parse, server perlu menentukan response yang sesuai. Buat file handlers.py dengan routing sederhana:
def handle_root():
return '200 OK', 'text/html', b'Hello from custom server
'
def handle_404():
return '404 Not Found', 'text/plain', b'Page not found'
def route(path):
if path == '/':
return handle_root()
return handle_404()Sekarang hubungkan routing dengan socket di server.py:
from handlers import route
def handle_request(client_socket):
data = client_socket.recv(4096)
if not data:
client_socket.close()
return
request = parse_request(data)
status, content_type, body = route(request['path'])
response = f'HTTP/1.1 {status}\r\n'.encode()
response += f'Content-Type: {content_type}\r\n'.encode()
response += f'Content-Length: {len(body)}\r\n'.encode()
response += b'\r\n'
response += body
client_socket.sendall(response)
client_socket.close()Fungsi handle_request membaca maksimal 4096 byte dari client, parse request, cari handler yang sesuai, lalu membangun HTTP response dengan header Content-Type dan Content-Length. Response di-encode menjadi byte sebelum dikirim melalui socket. Server ini sekarang bisa merespons request GET ke root path dengan HTML sederhana.
Web server yang hanya mengembalikan hardcoded HTML tidak terlalu berguna. Tambahkan kemampuan untuk serve file static dari direktori. Modifikasi handlers.py:
import os
def handle_static(path):
file_path = os.path.join('static', path.lstrip('/'))
if os.path.exists(file_path) and os.path.isfile(file_path):
with open(file_path, 'rb') as f:
content = f.read()
content_type = 'text/html' if file_path.endswith('.html') else 'application/octet-stream'
return '200 OK', content_type, content
return handle_404()
def route(path):
if path == '/':
return handle_root()
if path.startswith('/static/'):
return handle_static(path)
return handle_404()Fungsi handle_static memvalidasi keberadaan file sebelum membukanya. Path di-join dengan direktori static untuk mencegah directory traversal attack. Meskipun sederhana, mekanisme ini sudah cukup untuk serve file CSS, JavaScript, atau image ke client.
Server saat ini bersifat sequential: ia hanya bisa menangani satu request pada satu waktu. Jika satu request lambat, seluruh server terblokir. Solusinya adalah menambahkan threading sehingga setiap koneksi ditangani oleh thread terpisah.
Modifikasi server.py:
import threading
def start_server(host='127.0.0.1', port=8080):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((host, port))
server_socket.listen(5)
print(f'Server listening on {host}:{port}')
while True:
client_socket, address = server_socket.accept()
thread = threading.Thread(target=handle_request, args=(client_socket,))
thread.start()Dengan threading, server bisa menerima koneksi baru tanpa menunggu request sebelumnya selesai. Untuk production, model preforking atau event-driven seperti epoll lebih efisien. Namun, threading adalah langkah yang tepat untuk memahami koncurrency tanpa kompleksitas berlebihan.
Jalankan server dengan perintah python3 server.py, laku buka browser atau gunakan curl untuk testing:
curl -v http://127.0.0.1:8080/
curl -v http://127.0.0.1:8080/static/index.htmlFlag -v pada curl menampilkan header HTTP sehingga kamu bisa memverifikasi response yang dikirimkan server. Periksa apakah Content-Type dan Content-Length sesuai. Jika browser menampilkan halaman kosong, kemungkinan besar ada masalah pada header atau body delimiter.
Untuk debugging, tambahkan logging di setiap tahap: saat menerima koneksi, setelah parsing request, dan sebelum mengirim response. Log membantu mengidentifikasi apakah masalah terjadi di lapisan network, parsing, atau routing.
Membangun web server dari nol adalah latihan yang memberikan insight mendalam tentang bagaimana internet bekerja. Dari membuka socket TCP, parsing HTTP request, hingga menambahkan concurrency, setiap langkah memperkuat pemahaman tentang protocol dan networking. Tutorial ini hanya menyentuh permukaan. Dari sini, kamu bisa menambahkan SSL, compression, WebSocket, atau bahkan HTTP/2.
Repository Build Your Own X menyediakan lebih dari 150 tutorial untuk teknologi lainnya, mulai dari database, compiler, hingga operating system. Jika kamu menikmati tutorial ini, eksplorasi lebih lanjut akan membuka pemahaman baru tentang tool yang kamu gunakan setiap hari.
Source code lengkap tutorial ini dan referensi tambahan tersedia di GitHub CodeCrafters Build Your Own X. Artikel teknis mendalam tentang implementasi web server bisa dibaca di Better Programming: Writing Web Servers from First Principles.
Dapatkan feedback, users, dan eksposur dari komunitas kreator, developer, dan entrepreneur digital Indonesia.
Submit Produk → Pelajari Dulu