Kodeloka
  1. Kodeloka
  2. Kelas Nginx
  3. Materi

2 · Reverse Proxy · Modul 3 dari 8

Reverse Proxy & Header

Meneruskan permintaan ke aplikasi di belakang, dan memastikan aplikasi itu tahu siapa klien aslinya.

Bentuk Paling Sederhana

server {
    listen 80;
    server_name api.contoh.id;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Kenapa Header Itu Wajib

Begitu Nginx berdiri di depan aplikasi, aplikasi kehilangan seluruh konteks tentang klien. Yang dilihatnya hanyalah koneksi dari 127.0.0.1 melalui HTTP biasa. Empat header di atas mengembalikan konteks yang hilang itu.

$host                        # nama host yang diminta klien
$remote_addr                 # alamat IP klien
$proxy_add_x_forwarded_for   # rantai X-Forwarded-For + IP klien
$scheme                      # http atau https di sisi klien
🚫 Tanpa X-Forwarded-Proto, aplikasi terjebak lingkaran pengalihan

Aplikasi yang memaksa HTTPS melihat koneksi masuk sebagai http — karena memang begitu antara Nginx dan aplikasi. Ia lalu mengalihkan ke https://, permintaan kembali ke Nginx, diteruskan lagi sebagai HTTP, dan dialihkan lagi. Peramban akhirnya menyerah dengan ERR_TOO_MANY_REDIRECTS. Header ini memberi tahu aplikasi bahwa klien sudah memakai HTTPS.

Slash di Akhir proxy_pass Mengubah Segalanya

location /api/ {
    proxy_pass http://backend;       # TANPA slash
}
# /api/pengguna  →  http://backend/api/pengguna   (path utuh)

location /api/ {
    proxy_pass http://backend/;      # DENGAN slash
}
# /api/pengguna  →  http://backend/pengguna       (/api/ dipotong)
⚠️ Satu karakter, dua perilaku yang berbeda total

Bila proxy_pass berisi path apa pun — termasuk hanya / — Nginx mengganti bagian URI yang cocok dengan location. Bila hanya berisi host dan port, URI diteruskan apa adanya. Ini penyebab umum aplikasi hulu menerima path ganda seperti /api/api/pengguna.

Batas Waktu yang Perlu Disetel

proxy_connect_timeout   5s;     # membuka koneksi ke hulu
proxy_send_timeout      60s;    # mengirim permintaan ke hulu
proxy_read_timeout      60s;    # menunggu balasan dari hulu

proxy_buffering         on;
proxy_buffer_size       4k;
proxy_buffers           8 4k;

proxy_connect_timeout sebaiknya pendek — bila hulu tidak menjawab jabat tangan dalam 5 detik, ia memang sedang bermasalah dan menunggu lebih lama hanya menahan worker. Sebaliknya proxy_read_timeout harus mengikuti permintaan terlama yang wajar di aplikasi.

Buffering: Perisai untuk Klien Lambat

Dengan proxy_buffering on, Nginx membaca balasan dari hulu secepat mungkin, menyimpannya, lalu menyuapkan pelan-pelan ke klien. Aplikasi hulu dibebaskan setelah beberapa milidetik, bukan menunggu klien di jaringan lambat selesai mengunduh.

💡 Kapan buffering justru harus dimatikan

Untuk Server-Sent Events, streaming log, atau balasan bertahap, buffering menahan data sampai penuh sehingga klien seolah tidak menerima apa-apa. Matikan hanya pada location tersebut, bukan secara global.

location /stream/ {
    proxy_pass http://backend;
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 24h;
}

WebSocket

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade    $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 3600s;
}

Blok map diperlukan supaya header Connection hanya bernilai upgrade ketika permintaan memang ingin naik ke WebSocket, dan close untuk permintaan HTTP biasa yang melewati location yang sama.