(2) Returning HTML

1 parent 49df617b
...@@ -7,3 +7,15 @@ Dalam fungsi `handle_connection`, kita memproses request yang masuk dari browser ...@@ -7,3 +7,15 @@ Dalam fungsi `handle_connection`, kita memproses request yang masuk dari browser
3. **`.map(|result| result.unwrap())`**: Karena setiap baris yang dibaca mengembalikan tipe `Result` (bisa sukses atau error), kita menggunakan `.map()` dan `.unwrap()` untuk mengekstrak nilai `String` dari `Result::Ok` secara langsung (mengasumsikan tidak ada error saat pembacaan demi kesederhanaan). 3. **`.map(|result| result.unwrap())`**: Karena setiap baris yang dibaca mengembalikan tipe `Result` (bisa sukses atau error), kita menggunakan `.map()` dan `.unwrap()` untuk mengekstrak nilai `String` dari `Result::Ok` secara langsung (mengasumsikan tidak ada error saat pembacaan demi kesederhanaan).
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
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.
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()`.
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.
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello!</title>
</head>
<body>
<h1>Hello!</h1>
<p>Hi from Rust, running from my machine.</p>
</body>
</html>
\ No newline at end of file
use std::{ io::{ prelude::*, BufReader }, net::{ TcpListener, TcpStream } }; use std::{ fs, io::{ prelude::*, BufReader }, net::{ TcpListener, TcpStream } };
fn main() { fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
...@@ -12,11 +12,17 @@ fn main() { ...@@ -12,11 +12,17 @@ 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 let _http_request: Vec<_> = buf_reader
.lines() .lines()
.map(|result| result.unwrap()) .map(|result| result.unwrap())
.take_while(|line| !line.is_empty()) .take_while(|line| !line.is_empty())
.collect(); .collect();
println!("Request: {:#?}", http_request); let status_line = "HTTP/1.1 200 OK";
let contents = fs::read_to_string("hello.html").unwrap();
let length = contents.len();
let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
stream.write_all(response.as_bytes()).unwrap();
} }
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!