proxy_pass

proxy_pass #

proxy_pass adalah directive inti dari reverse proxy Nginx. Ia menentukan ke mana request harus diteruskan. Meskipun terlihat sederhana, ada beberapa detail penting yang mempengaruhi bagaimana URI request dimodifikasi sebelum dikirim ke backend.

Penggunaan Dasar #

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
    }
}

Setiap request ke example.com akan diteruskan ke proses yang berjalan di port 3000 pada mesin yang sama.


Detail Penting: Trailing Slash #

Ini adalah bagian yang paling sering menyebabkan bug halus. Perilaku proxy_pass berbeda tergantung ada atau tidaknya trailing slash (atau path apapun) di nilai proxy_pass.

Tanpa URI di proxy_pass #

location /api/ {
    proxy_pass http://localhost:3000;
    # Request: /api/users → diteruskan ke backend sebagai: /api/users
    # URI tidak dimodifikasi sama sekali
}

Ketika proxy_pass tidak menyertakan URI (hanya http://host atau http://host:port), Nginx meneruskan URI request apa adanya ke backend.

Dengan URI di proxy_pass #

location /api/ {
    proxy_pass http://localhost:3000/;
    # Request: /api/users → diteruskan ke backend sebagai: /users
    # Bagian /api/ digantikan dengan /
}

location /api/ {
    proxy_pass http://localhost:3000/v2/;
    # Request: /api/users → diteruskan ke backend sebagai: /v2/users
    # Bagian /api/ digantikan dengan /v2/
}

Ketika proxy_pass menyertakan URI (bahkan hanya trailing slash /), Nginx menggantikan bagian yang cocok dengan location dengan URI yang ada di proxy_pass.

Perbandingan Langsung #

# Skenario: request masuk GET /api/users/123

location /api/ {
    proxy_pass http://backend;
    # Backend terima: GET /api/users/123
}

location /api/ {
    proxy_pass http://backend/;
    # Backend terima: GET /users/123
}

location /api/ {
    proxy_pass http://backend/service/;
    # Backend terima: GET /service/users/123
}

Tidak ada yang “lebih benar” — keduanya berguna tergantung bagaimana backend dikonfigurasi. Yang penting adalah memahami perbedaannya agar tidak ada mismatch antara path yang dikirim Nginx dan path yang diharapkan backend.


Proxy ke Unix Socket #

Untuk performa lebih baik pada mesin yang sama, gunakan Unix socket daripada TCP localhost:

# PHP-FPM via Unix socket
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    # ...
}

# Atau untuk HTTP proxy ke aplikasi yang listen di socket
location / {
    proxy_pass http://unix:/run/myapp/myapp.sock;
}

Unix socket menghindari overhead TCP stack (tidak perlu buka/tutup koneksi TCP, tidak ada network roundtrip) — lebih cepat untuk komunikasi lokal antar proses.


proxy_http_version #

Secara default Nginx menggunakan HTTP/1.0 untuk koneksi ke backend. Ini perlu diubah ke 1.1 jika kamu menggunakan keepalive ke backend atau butuh chunked transfer encoding:

location / {
    proxy_pass http://backend;
    proxy_http_version 1.1;

    # Untuk keepalive ke backend, header Connection harus dikosongkan
    proxy_set_header Connection "";
}

HTTP/1.1 ke backend penting untuk:

  • WebSocket (membutuhkan upgrade dari HTTP/1.1)
  • Keepalive connections ke upstream (mengurangi overhead buka tutup koneksi)
  • Chunked transfer encoding

Proxy ke Upstream Group #

Dalam praktik nyata, proxy_pass sering mengarah ke upstream group daripada alamat tunggal. Ini memungkinkan load balancing dan failover:

upstream backend_servers {
    server 10.0.0.1:3000;
    server 10.0.0.2:3000;
    server 10.0.0.3:3000;
}

server {
    location / {
        proxy_pass http://backend_servers;
    }
}

Detail tentang upstream dan load balancing dibahas di Section 06.


Proxy dengan Modifikasi Path #

Kadang kamu perlu mengubah path request sebelum diteruskan ke backend. Ada beberapa cara:

Menggunakan trailing slash (cara paling sederhana) #

# /app/users → backend menerima /users
location /app/ {
    proxy_pass http://localhost:8080/;
}

Menggunakan rewrite #

# Hapus prefix /api/v1 sebelum diteruskan ke backend
location /api/v1/ {
    rewrite ^/api/v1/(.*) /$1 break;
    proxy_pass http://localhost:3000;
}

Menggunakan sub_filter untuk konten response #

# Ganti URL absolut dalam response HTML dari backend
location / {
    proxy_pass http://backend;
    sub_filter 'http://internal-backend' 'https://example.com';
    sub_filter_once off;
}

Konfigurasi proxy_pass yang Lengkap #

Ini konfigurasi reverse proxy yang lebih lengkap dengan semua elemen penting:

server {
    listen 80;
    server_name example.com;

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

        # Header agar backend tahu informasi klien asli
        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;

        # Untuk WebSocket / keepalive
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

Header Upgrade dan Connection untuk WebSocket perlu dibuat dengan map karena nilainya kondisional:

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

    server {
        location / {
            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade    $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

Ringkasan #

  • Tanpa URI di proxy_pass: URI request diteruskan apa adanya. Dengan URI (termasuk trailing /): bagian yang cocok dengan location digantikan.
  • Gunakan proxy_http_version 1.1 dan proxy_set_header Connection "" untuk keepalive ke backend.
  • Unix socket (http://unix:/path/to/sock) lebih cepat dari TCP localhost untuk komunikasi antar proses di mesin yang sama.
  • Selalu sertakan header X-Real-IP, X-Forwarded-For, dan X-Forwarded-Proto agar backend tahu informasi asli klien.
  • Untuk WebSocket, gunakan map untuk menentukan nilai header Connection secara kondisional.

← Sebelumnya: Konsep Reverse Proxy   Berikutnya: Proxy Headers →

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