Troubleshooting

Cara Mengatasi Error CORS pada Elasticsearch

Error CORS muncul ketika aplikasi browser mencoba mengakses langsung endpoint Elasticsearch di port 9200 dari origin berbeda. Browser memblokirnya demi keamanan. Panduan ini menjelaskan penyebabnya, konfigurasi http.cors.* yang benar, perbedaan setelan aman vs longgar, dan kenapa reverse proxy adalah solusi terbaik.

Kenapa CORS Muncul?

CORS (Cross-Origin Resource Sharing) adalah kebijakan keamanan browser. Ketika halaman di https://panel.contoh.com memanggil API di http://server:9200, keduanya beda origin (protokol/host/port). Browser hanya mengizinkan respons bila server membalas header Access-Control-Allow-Origin yang cocok.

Secara default, Elasticsearch tidak mengirim header CORS apa pun, sehingga panggilan dari browser ke 9200 langsung gagal.

CORS bukan masalah Elasticsearch itu sendiri — curl dan klien server-side tetap berfungsi normal. Yang memblokir adalah browser pengguna.

Pesan Error Tipikal

# di konsol browser (DevTools)
Access to fetch at 'http://10.0.0.5:9200/_cluster/health'
from origin 'https://panel.contoh.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
# varian preflight gagal
Response to preflight request doesn't pass access control check:
It does not have HTTP ok status.

Permintaan dengan method non-sederhana (mis. PUT, DELETE, atau header Content-Type: application/json) memicu preflight OPTIONS yang juga harus dijawab dengan header CORS.

Konfigurasi http.cors di elasticsearch.yml

Semua setelan CORS diatur di elasticsearch.yml dan butuh restart node untuk berlaku (ini static settings, bukan dynamic).

SettingFungsiDefault
http.cors.enabledMengaktifkan penanganan CORS.false
http.cors.allow-originOrigin yang diizinkan (string atau /regex/).kosong
http.cors.allow-credentialsIzinkan cookie/Authorization lintas-origin.false
http.cors.allow-methodsMethod HTTP yang diizinkan.OPTIONS,HEAD,GET,POST,PUT,DELETE
http.cors.allow-headersHeader request yang diizinkan.X-Requested-With,Content-Type,Content-Length,Authorization

Contoh Konfigurasi Aman vs Longgar

Aman — origin spesifik (disarankan bila harus akses browser)

# elasticsearch.yml
http.cors.enabled: true
http.cors.allow-origin: "https://panel.contoh.com"
http.cors.allow-credentials: true
http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE
http.cors.allow-headers: X-Requested-With, Content-Type, Content-Length, Authorization
Untuk beberapa origin, pakai regex: http.cors.allow-origin: "/https?://(panel|admin)\.contoh\.com/" (apit dengan garis miring).

Longgar — wildcard (hanya untuk dev lokal)

# JANGAN dipakai di produksi terbuka
http.cors.enabled: true
http.cors.allow-origin: "*"
Kombinasi allow-origin: "*" dengan allow-credentials: true ditolak browser dan berbahaya. Jika cluster Anda tanpa autentikasi dan terekspos, wildcard memungkinkan situs mana pun memanggil cluster lewat browser korban. Hindari di produksi.

Solusi yang Lebih Baik: Reverse Proxy

Daripada membuka 9200 ke browser, sajikan panel dan API dari origin yang sama lewat Nginx. Karena tidak lagi lintas-origin, CORS jadi tidak relevan — sekaligus Anda dapat HTTPS, Basic Auth, dan IP whitelist.

# nginx — panel & API di origin yang sama
server {
  server_name panel.contoh.com;

  location /es/ {
    proxy_pass http://127.0.0.1:9200/;
    proxy_set_header Host $host;
  }

  location / {
    proxy_pass http://127.0.0.1:8080/;   # nusabet88
  }
}
nusabet88 meneruskan permintaan ke Elasticsearch dari sisi server, bukan dari browser. Dengan begitu Anda terhindar dari CORS sepenuhnya dan tidak perlu mengaktifkan http.cors.* sama sekali.

Verifikasi

# uji header CORS dengan preflight OPTIONS
curl -i -X OPTIONS http://server:9200/_cluster/health \
  -H "Origin: https://panel.contoh.com" \
  -H "Access-Control-Request-Method: GET"

# respons yang diharapkan memuat:
Access-Control-Allow-Origin: https://panel.contoh.com
Access-Control-Allow-Methods: OPTIONS, HEAD, GET, POST, PUT, DELETE

Kesimpulan

  • CORS ditegakkan browser; curl tidak terpengaruh — masalahnya muncul saat browser akses 9200 langsung.
  • Bila harus mengizinkan browser, set allow-origin ke origin spesifik, bukan "*".
  • Jangan kombinasikan wildcard origin dengan allow-credentials: true.
  • Solusi terbaik: reverse proxy origin tunggal atau pakai nusabet88 yang meneruskan dari sisi server — CORS jadi tidak relevan.

FAQ Error CORS

Kenapa error CORS hanya muncul di browser, bukan di curl?

CORS (Cross-Origin Resource Sharing) adalah mekanisme keamanan yang ditegakkan oleh browser, bukan oleh Elasticsearch. curl dan klien server-side tidak peduli pada origin, sehingga tidak terkena CORS. Browser memblokir respons lintas-origin kecuali server mengirim header Access-Control-Allow-Origin yang sesuai.

Apakah aman mengaktifkan http.cors.allow-origin: "*"?

Tidak untuk produksi. Tanda * mengizinkan situs mana pun memanggil cluster Anda dari browser pengguna. Jika cluster terekspos tanpa autentikasi, ini berbahaya. Batasi ke origin spesifik (https://panel.domain.com) dan idealnya jangan ekspos 9200 ke browser sama sekali — pakai reverse proxy.

Saya pakai kredensial, kenapa request tetap gagal?

Jika klien mengirim cookie atau Authorization, Anda harus menyetel http.cors.allow-credentials: true dan TIDAK boleh memakai allow-origin "*". Browser menolak kombinasi wildcard origin dengan credentials. Tentukan origin eksplisit.

Apa solusi terbaik selain mengaktifkan CORS?

Letakkan reverse proxy (Nginx) di depan Elasticsearch dan sajikan panel pada origin yang sama dengan API. Karena tidak lagi lintas-origin, CORS tidak relevan, dan Anda bisa menambah HTTPS, Basic Auth, serta IP whitelist sekaligus. nusabet88 sendiri sudah meneruskan request dari sisi server sehingga menghindari masalah ini.

Hindari CORS dengan reverse proxy

Sajikan panel dan API dari origin yang sama lewat Nginx + HTTPS. CORS hilang, keamanan naik.

Panduan Nginx + HTTPS