KnowTheHeaders: CORS (Part 1)

Sebelum masuk ke topik, mari kita bahas dulu sedikit seputar latar belakang tulisan ini. Pada 28 April 2020, kita membuat polling seputar dunia per-web-an: > halo sobat spider, buat kamu yang sedang/ingin menjadi web developer, tantangan kamu sekarang ini apa ciii? — evilfactorylabs (@evilfactorylabs) April 28, 2020 [https://twitter.com/evilfactorylabs/status/1255122105777090572?ref_src=twsrc%5Etfw] Ternyata persentase yang paling banyak adalah ~42.9%, yang mana memilih "lagi mendalami fundam

Sebelum masuk ke topik, mari kita bahas dulu sedikit seputar latar belakang tulisan ini.

Pada 28 April 2020, kita membuat polling seputar dunia per-web-an:

Ternyata persentase yang paling banyak adalah ~42.9%, yang mana memilih "lagi mendalami fundamental". Gue yakin kalau kita ingin berbicara tentang fundamental, kita harus memiliki batas ambang.

Karena... Cara kerja TCP/UDP juga termasuk bagian fundamental untuk pengembang web, bukan?

Oke oke, kita udah sering banget ngedenger saran senior seputar fundamental, kan ya. Sederhananya, fundamental ini hal-hal dasar gitu lah. Gini nih kalau gak belajar fundamental, masa taunya cuma ngubah CNAME di React? Giliran vanilla gak bisa dia. Gitu nada nya.

Yaudahlah ya, menurut gue, ada satu hal mendasar yang keberadaannya mudah sekali dihiraukan oleh pengembang web: Headers, alias HTTP Headers.

Sebenarnya ada banyak Headers yang ada di HTTP, dan dibagian #KnowTheHeaders ini kita akan berbagi header-header yang sekiranya baik untuk diketahui untuk sobat spider nih.

Header pertama yang akan kita bahas adalah seputar Cross-Origin Resource Sharing (CORS), sebuah keamanan—yang terkadang menjadi masalah—untuk seseorang yang membuat aplikasi web.

Apa?

CORS ini adalah sebuah "cara" untuk memberitahu browser bahwa kita ingin mengakses resources yang berada di origin berbeda. Mekanisme nya adalah dengan menambahkan beberapa HTTP Headers.

Kasus sederhana nya, kita sedang membuat Backend for Frontend. Di development, frontend kita berada di port 8080 dan backend berada di port 3000. Meskipun hostname nya sama-sama localhost, tapi ini berbeda origin karena singkatnya memang bukan berasal dari sumber yang sama (beda port).

Kita mengirim request ke /api/v1/posts yang port 3000 tersebut, yang mana response nya adalah berbentuk JSON. Biasanya, request tersebut gagal (meskipun tidak 100% gagal) bila server tidak mengirimkan header access-control-allow-origin, sehingga browser mem-block request tersebut karena menuju ke origin yang berbeda dengan alasan keamanan.

Jika server memberikan response header secara eksplisit access-control-allow-origin: http://localhost:3000, maka yang boleh melakukan cross-origin request hanya dari origin itu, bukan yang lain.

Bagaimana?

Jika kita (salah satunya) membuat request menggunakan XMLHttpRequest ataupun Fetch API ke origin yang berbeda (beda protokol, hostname, ataupun port), server perlu secara eksplisit memberitahu origin mana saja yang boleh melakukan cross-origin request tersebut.

Itu adalah salah satu contohnya, buka gambar di tab baru untuk memperjelas.

Disitu dijelaskan bahwa:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://donat.edgy.network/api/v1/supporters?api_key=xxx. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘https://blog.evilfactory.id’).

Yang mana disitu kita buat eksplisit request tersebut hanya valid untuk blog.evilfactory.id bila dari berbeda origin, selainnya, ya tolak (request diatas berasal dari desk.evilfactory.id).

Jadi, untuk yang mengembangkan aplikasi web yang memisahkan backend dengan frontend, CORS ini adalah hal dasar yang menarik untuk diketahui.

Preflight

Bila kita melihat devtools di browser yang kita gunakan, terkadang kita melihat request ke endpoint yang sama namun menggunakan metoda yang berbeda, yakni OPTIONS.

Yang mana, itu disebut dengan Preflighted Request.

Sederhananya, request ini adalah untuk menentukan apakah request asli nya tersebut aman untuk dikirim atau tidak, dengan mengirim request dengan method OPTIONS dan membawa beberapa headers.

Misal, request OPTIONS tersebut memiliki request header seperti ini:

Host: localhost:3000
Accept: */*
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Origin: http://localhost:3001
DNT: 1
Connection: keep-alive

Berdasarkan konfigurasi yang kamu lakukan di server, misal response dari server nya kurang lebih seperti ini:

HTTP/1.1 204 No Content
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,HEAD,PUT,DELETE,PATCH
Access-Control-Allow-Headers: authorization

Berdasarkan dari response tersebut, kita bisa melakukan request benerannya, yang mana method asli nya adalah GET dan juga kita ingin mengirim header Authorization.

Dan dari contoh diatas, cross-origin yang dibolehkan adalah dari mana saja (alias *).

Misalnya request aslinya adalah seperti ini:

Host: localhost:3000
Accept: */*
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInxxx.eyJlexxxfQ.AAxxx
Origin: http://localhost:3001
DNT: 1
Connection: keep-alive

Tidak beda jauh, yang membedakan request tersebut memiliki method GET dan membawa header Authorization.

Dengan melakukan preflight, browser bisa mengetahui apakah request tersebut aman untuk dijalankan atau tidak. Jadi, jangan masalah dengan banyaknya request ber-method OPTIONS yang ada di devtools mu!

Penutup

Di part 2 nanti, kita akan menyelam lebih dalam dengan header-header lain seputar CORS, berikut dengan implementasi sederhananya, thank you.

Menikmati tulisan ini?

Blog ini tidak menampilkan iklan, yang berarti blog ini didanai oleh pembaca seperti kamu. Gabung bersama yang telah membantu blog ini agar terus bisa mencakup tulisan yang lebih berkualitas dan bermanfaat!

Pendukung

Kamu?