(4) Simulation of slow request.

1 parent 1e837cf1
Showing with 25 additions and 7 deletions
...@@ -27,4 +27,13 @@ Pada code yang baru ditambahkan di `handle_connection`, server sekarang mengirim ...@@ -27,4 +27,13 @@ Pada code yang baru ditambahkan di `handle_connection`, server sekarang mengirim
Pada tahap ini, kita memvalidasi request HTTP yang masuk agar server tidak merespons semua request dengan `hello.html`. 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`. 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. 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
# Commit 4 Reflection notes
Pada tahap ini, kita menambahkan rute `/sleep` yang akan melakukan simulasi proses lambat dengan menghentikan *thread* selama 10 detik (`thread::sleep`).
Dari hasil percobaan membuka dua *browser window*, ketika kita mengakses `/sleep` di window pertama dan segera mengakses `/` di window kedua, window kedua tertahan (*loading* terus) dan baru memuat halaman setelah window pertama selesai.
**Kenapa ini terjadi?**
Ini terjadi karena web server yang kita bangun saat ini bersifat **Single-Threaded**. Artinya, server hanya memproses satu *request* pada satu waktu secara berurutan. Ketika rute `/sleep` diakses, satu-satunya *thread* yang dimiliki program akan delay selama 10 detik. Selama masa itu, *thread* tersebut *blocked* dan tidak bisa menerima atau memproses koneksi baru yang masuk (seperti *request* ke `/` dari window kedua). Window kedua harus menunggu dalam antrean sistem operasi (TCP queue) sampai *thread* utama selesai memproses rute `/sleep`. Ini menunjukkan bahwa server *single-thread* sangat tidak optimal dan tidak tangguh untuk menangani banyak koneksi (karena *bottleneck*).
\ No newline at end of file
use std::{ fs, io::{ prelude::*, BufReader }, net::{ TcpListener, TcpStream } }; use std::{
fs,
io::{ prelude::*, BufReader },
net::{ TcpListener, TcpStream },
thread,
time::Duration,
};
fn main() { fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
...@@ -15,10 +21,13 @@ fn handle_connection(mut stream: TcpStream) { ...@@ -15,10 +21,13 @@ fn handle_connection(mut stream: TcpStream) {
let request_line = buf_reader.lines().next().unwrap().unwrap(); let request_line = buf_reader.lines().next().unwrap().unwrap();
let (status_line, filename) = if request_line == "GET / HTTP/1.1" { let (status_line, filename) = match &request_line[..] {
("HTTP/1.1 200 OK", "hello.html") "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"),
} else { "GET /sleep HTTP/1.1" => {
("HTTP/1.1 404 NOT FOUND", "404.html") thread::sleep(Duration::from_secs(10));
("HTTP/1.1 200 OK", "hello.html")
}
_ => ("HTTP/1.1 404 NOT FOUND", "404.html"),
}; };
let contents = fs::read_to_string(filename).unwrap(); let contents = fs::read_to_string(filename).unwrap();
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!