(3) Validating request and selectively responding

1 parent ae892593
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Not Found</title>
</head>
<body>
<h1>Oops!</h1>
<p>Sorry, I don't know what you're asking for.</p>
<p>Rust is running from my machine.</p>
</body>
</html>
\ No newline at end of file
...@@ -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.
![Commit 2 screen capture](assets/images/commit2.png)
# Commit 2 Reflection notes # Commit 2 Reflection notes
![Commit 2 screen capture](assets/images/commit2.png)
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.
\ No newline at end of file
# Commit 3 Reflection notes
![Commit 3 screen capture](assets/images/commit3.png)
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.
\ No newline at end of file
...@@ -12,14 +12,16 @@ fn main() { ...@@ -12,14 +12,16 @@ fn main() {
fn handle_connection(mut stream: TcpStream) { fn handle_connection(mut stream: TcpStream) {
let buf_reader = BufReader::new(&mut stream); let buf_reader = BufReader::new(&mut stream);
let _http_request: Vec<_> = buf_reader
.lines() let request_line = buf_reader.lines().next().unwrap().unwrap();
.map(|result| result.unwrap())
.take_while(|line| !line.is_empty()) let (status_line, filename) = if request_line == "GET / HTTP/1.1" {
.collect(); ("HTTP/1.1 200 OK", "hello.html")
} else {
let status_line = "HTTP/1.1 200 OK"; ("HTTP/1.1 404 NOT FOUND", "404.html")
let contents = fs::read_to_string("hello.html").unwrap(); };
let contents = fs::read_to_string(filename).unwrap();
let length = contents.len(); let length = contents.len();
let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!