@@ -8,14 +8,23 @@ Dalam fungsi `handle_connection`, kita memproses request yang masuk dari browser
...
@@ -8,14 +8,23 @@ Dalam fungsi `handle_connection`, kita memproses request yang masuk dari browser
4.**`.take_while(|line| !line.is_empty())`**: HTTP request header selalu diakhiri dengan dua buah *newline* (baris kosong). Fungsi ini akan terus membaca baris dari stream *sampai* menemukan baris kosong tersebut, lalu berhenti. Ini mencegah program *hang* karena menunggu data yang tidak akan dikirim lagi oleh browser.
4.**`.take_while(|line| !line.is_empty())`**: HTTP request header selalu diakhiri dengan dua buah *newline* (baris kosong). Fungsi ini akan terus membaca baris dari stream *sampai* menemukan baris kosong tersebut, lalu berhenti. Ini mencegah program *hang* karena menunggu data yang tidak akan dikirim lagi oleh browser.
5.**`.collect()`**: Mengumpulkan semua baris teks yang sudah diproses di atas ke dalam sebuah koleksi vektor (`Vec<_>`), yang kemudian kita simpan ke variabel `http_request` untuk di-print.
5.**`.collect()`**: Mengumpulkan semua baris teks yang sudah diproses di atas ke dalam sebuah koleksi vektor (`Vec<_>`), yang kemudian kita simpan ke variabel `http_request` untuk di-print.
Pada code yang baru ditambahkan di `handle_connection`, server sekarang mengirimkan response yang valid sesuai HTTP Protocol. Berikut hal baru yang dipelajari:
Pada code yang baru ditambahkan di `handle_connection`, server sekarang mengirimkan response yang valid sesuai HTTP Protocol. Berikut hal baru yang dipelajari:
1.**`fs::read_to_string("hello.html")`**: Digunakan untuk membaca seluruh isi file HTML dan mengubahnya menjadi tipe data `String` di Rust agar bisa dikirimkan sebagai *body* dari HTTP response.
1.**`fs::read_to_string("hello.html")`**: Digunakan untuk membaca seluruh isi file HTML dan mengubahnya menjadi tipe data `String` di Rust agar bisa dikirimkan sebagai *body* dari HTTP response.
2.**`HTTP/1.1 200 OK`**: Ini adalah *status line* standar dari HTTP yang memberitahu browser bahwa *request* berhasil diproses.
2.**`HTTP/1.1 200 OK`**: Ini adalah *status line* standar dari HTTP yang memberitahu browser bahwa *request* berhasil diproses.
3.**`Content-Length`**: Header HTTP yang wajib disertakan agar browser tahu seberapa besar ukuran data (dalam byte) yang akan diterima. Kita menghitungnya menggunakan `contents.len()`.
3.**`Content-Length`**: Header HTTP yang wajib disertakan agar browser tahu seberapa besar ukuran data (dalam byte) yang akan diterima. Kita menghitungnya menggunakan `contents.len()`.
4.**Format Response (`\r\n\r\n`)**: Protokol HTTP mensyaratkan penggunaan CRLF (`\r\n`) untuk memisahkan setiap baris header. Selain itu, harus ada dua buah CRLF (`\r\n\r\n`) yang berfungsi sebagai pemisah mutlak antara bagian *Headers* dan bagian *Body* (isi konten HTML).
4.**Format Response (`\r\n\r\n`)**: Protokol HTTP mensyaratkan penggunaan CRLF (`\r\n`) untuk memisahkan setiap baris header. Selain itu, harus ada dua buah CRLF (`\r\n\r\n`) yang berfungsi sebagai pemisah mutlak antara bagian *Headers* dan bagian *Body* (isi konten HTML).
5.**`stream.write_all`**: Mengirimkan seluruh *string* balasan yang sudah diformat tadi (diubah menjadi *bytes*) kembali melalui TCP stream ke browser.
5.**`stream.write_all`**: Mengirimkan seluruh *string* balasan yang sudah diformat tadi (diubah menjadi *bytes*) kembali melalui TCP stream ke browser.
Pada tahap ini, kita memvalidasi request HTTP yang masuk agar server tidak merespons semua request dengan `hello.html`.
1.**Cara memisahkan respons:** Kita membaca baris pertama dari HTTP request (`request_line`). Jika baris tersebut sama persis dengan `"GET / HTTP/1.1"`, kita mengembalikan `hello.html` dengan status `200 OK`. Jika request line berupa hal lain (misalnya `/bad`), kita masuk ke blok `else` dan mengembalikan `404.html` dengan status `404 NOT FOUND`.
2.**Kenapa refactoring diperlukan:** Pada awalnya, blok `if` dan `else` memiliki banyak duplikasi kode (seperti pemanggilan `fs::read_to_string`, penghitungan *length*, dan format response). Membiarkan kode duplikat bertentangan dengan prinsip *Clean Code* (DRY - *Don't Repeat Yourself*). Dengan melakukan refactoring, kita hanya menggunakan blok `if-else` untuk menentukan `status_line` dan `filename`, lalu mengeksekusi logika pembacaan file dan pengiriman respons secara universal di luar blok kondisi tersebut. Ini membuat kode lebih bersih, mudah dibaca, dan mudah di-maintenance jika nanti kita ingin menambahkan modifikasi pada format respons HTTP.